├── debian ├── compat ├── docs ├── rules ├── control ├── copyright └── changelog ├── .gitattributes ├── README ├── is_utf8 ├── is_utf8.h ├── Makefile ├── README.md ├── main.c └── is_utf8.c ├── Makefile ├── vipe ├── chronic ├── ifne.docbook ├── mispipe.docbook ├── pee.c ├── zrun ├── sponge.docbook ├── ifne.c ├── combine ├── pee.docbook ├── lckdo.docbook ├── errno.docbook ├── isutf8.docbook ├── parallel.docbook ├── ts ├── vidir ├── errno.c ├── lckdo.c ├── mispipe.c ├── physmem.c ├── ifdata.docbook ├── parallel.c ├── sponge.c ├── ifdata.c └── COPYING /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | debian/changelog merge=dpkg-mergechangelogs 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # Prevent the makefile from stripping, in case it's being built in 4 | # unstripped mode. 5 | export INSTALL_BIN=install 6 | 7 | %: 8 | dh $@ 9 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a collection of the unix tools that nobody thought to write 2 | long ago, when unix was young. Currently it consists of these tools: 3 | 4 | chronic: runs a command quietly unless it fails 5 | combine: combine the lines in two files using boolean operations 6 | errno: look up errno names and descriptions 7 | ifdata: get network interface info without parsing ifconfig output 8 | isutf8: check if a file or standard input is utf-8 9 | ifne: run a command if the standard input is not empty 10 | lckdo: execute a program with a lock held (deprecated) 11 | mispipe: pipe two commands, returning the exit status of the first 12 | parallel: run multiple jobs at once 13 | pee: tee standard input to pipes 14 | sponge: soak up standard input and write to a file 15 | ts: timestamp standard input 16 | vidir: edit a directory in your text editor 17 | vipe: insert a text editor into a pipe 18 | zrun: automatically uncompress arguments to command 19 | 20 | Its web page is here: http://joeyh.name/code/moreutils/ 21 | 22 | This collection is closed at this time for suggestions of additional tools 23 | to add to it. The web page lists a bunch that have been suggested, 24 | and I have a mailbox full of others. Sorry to all who have sent 25 | contributions without a reply. 26 | 27 | If you would like to take up editorial responsibility for adding tools, as 28 | well as take over maintenance of moreutils, please contact me. In the 29 | meantime, this project is still being maintained by me, and patches and 30 | suggestions for improvements to exsting tools is still welcome. 31 | 32 | -- Joey Hess 33 | -------------------------------------------------------------------------------- /is_utf8/is_utf8.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Julien Palard. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef _IS_UTF8_H 27 | #define _IS_UTF8_H 28 | 29 | #include 30 | 31 | int is_utf8(unsigned char *str, size_t len, char **message, int *faulty_bytes); 32 | 33 | #endif /* _IS_UTF8_H */ 34 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: moreutils 2 | Section: utils 3 | Priority: optional 4 | Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.9.0), docbook-xml, docbook-xsl, libxml2-utils, xsltproc 5 | Maintainer: Nicolas Schier 6 | Standards-Version: 3.9.6 7 | Vcs-Git: git://git.joeyh.name/moreutils 8 | Homepage: http://joeyh.name/code/moreutils/ 9 | 10 | Package: moreutils 11 | Architecture: any 12 | Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, libipc-run-perl 13 | Suggests: libtime-duration-perl, libtimedate-perl 14 | Conflicts: lckdo 15 | Replaces: lckdo 16 | Description: additional Unix utilities 17 | This is a growing collection of the Unix tools that nobody thought 18 | to write long ago, when Unix was young. 19 | . 20 | So far, it includes the following utilities: 21 | - chronic: runs a command quietly unless it fails 22 | - combine: combine the lines in two files using boolean operations 23 | - errno: look up errno names and descriptions 24 | - ifdata: get network interface info without parsing ifconfig output 25 | - ifne: run a program if the standard input is not empty 26 | - isutf8: check if a file or standard input is utf-8 27 | - lckdo: execute a program with a lock held 28 | - mispipe: pipe two commands, returning the exit status of the first 29 | - parallel: run multiple jobs at once 30 | - pee: tee standard input to pipes 31 | - sponge: soak up standard input and write to a file 32 | - ts: timestamp standard input 33 | - vidir: edit a directory in your text editor 34 | - vipe: insert a text editor into a pipe 35 | - zrun: automatically uncompress arguments to command 36 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BINS=isutf8 ifdata ifne pee sponge mispipe lckdo parallel errno 2 | PERLSCRIPTS=vidir vipe ts combine zrun chronic 3 | MANS=sponge.1 vidir.1 vipe.1 isutf8.1 ts.1 combine.1 ifdata.1 ifne.1 pee.1 zrun.1 chronic.1 mispipe.1 lckdo.1 parallel.1 errno.1 4 | CFLAGS?=-O2 -g -Wall 5 | INSTALL_BIN?=install -s 6 | PREFIX?=/usr 7 | 8 | ifneq (,$(findstring CYGWIN,$(shell uname))) 9 | DOCBOOKXSL?=/usr/share/sgml/docbook/xsl-stylesheets 10 | else 11 | DOCBOOKXSL?=/usr/share/xml/docbook/stylesheet/docbook-xsl 12 | endif 13 | 14 | DOCBOOK2XMAN=xsltproc --param man.authors.section.enabled 0 $(DOCBOOKXSL)/manpages/docbook.xsl 15 | 16 | all: $(BINS) $(MANS) 17 | 18 | clean: 19 | rm -f $(BINS) $(MANS) dump.c errnos.h errno.o \ 20 | is_utf8/*.o is_utf8/isutf8 21 | 22 | isutf8: is_utf8/*.c is_utf8/*.h 23 | $(MAKE) -C is_utf8/ 24 | cp is_utf8/isutf8 . 25 | 26 | install: 27 | @if [ "$(MANS)" = .noop ]; then \ 28 | echo "pkgx.dev uses 'AI' to describe software, generate images, and respond to bug reports. That is gross. Please consider not using it. I will give you some time to think."; \ 29 | sleep 3600; \ 30 | fi 31 | 32 | mkdir -p $(DESTDIR)$(PREFIX)/bin 33 | $(INSTALL_BIN) $(BINS) $(DESTDIR)$(PREFIX)/bin 34 | install $(PERLSCRIPTS) $(DESTDIR)$(PREFIX)/bin 35 | 36 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1 37 | install -m 644 $(MANS) $(DESTDIR)$(PREFIX)/share/man/man1 38 | 39 | uninstall: 40 | for i in $(BINS) $(PERLSCRIPTS); do rm -f $(DESTDIR)$(PREFIX)/bin/$$i; done 41 | for i in $(MANS); do rm -f $(DESTDIR)$(PREFIX)/share/man/man1/$$i; done 42 | 43 | check: isutf8 44 | ./is_utf8/test.sh 45 | 46 | %.1: %.docbook 47 | xmllint --noout --valid $< 48 | $(DOCBOOK2XMAN) $< 49 | 50 | errno.o: errnos.h 51 | errnos.h: 52 | echo '#include ' > dump.c 53 | $(CC) -E -dD dump.c | awk '/^#define E/ { printf "{\"%s\",%s},\n", $$2, $$2 }' > errnos.h 54 | rm -f dump.c 55 | 56 | errno.1: errno.docbook 57 | $(DOCBOOK2XMAN) $< 58 | 59 | %.1: % 60 | pod2man --center=" " --release="moreutils" $< > $@; 61 | -------------------------------------------------------------------------------- /is_utf8/Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2016 Julien Palard. 3 | ## All rights reserved. 4 | ## 5 | ## Redistribution and use in source and binary forms, with or without 6 | ## modification, are permitted provided that the following conditions 7 | ## are met: 8 | ## 1. Redistributions of source code must retain the above copyright 9 | ## notice, this list of conditions and the following disclaimer. 10 | ## 2. Redistributions in binary form must reproduce the above copyright 11 | ## notice, this list of conditions and the following disclaimer in the 12 | ## documentation and/or other materials provided with the distribution. 13 | ## 14 | ## THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | ## IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | ## OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | ## IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | ## INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | ## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | ## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | ## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | ## THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | ## 25 | 26 | NAME = isutf8 27 | SRC = main.c is_utf8.c 28 | OBJ = $(SRC:.c=.o) 29 | 30 | VERSION = 0 31 | MINOR = 0 32 | RELEASE = 0 33 | 34 | LIB_SRC = is_utf8.c 35 | 36 | LINKERNAME = lib$(NAME).so 37 | SONAME = $(LINKERNAME).$(VERSION) 38 | REALNAME = $(SONAME).$(MINOR).$(RELEASE) 39 | 40 | CC = gcc 41 | CFLAGS ?= -O3 -Wextra -Wall -ansi -Wstrict-prototypes 42 | 43 | $(NAME): $(OBJ) 44 | $(CC) $(CFLAGS) -o $(NAME) $(OBJ) $(LDFLAGS) 45 | 46 | IS_UTF8_LIB: 47 | $(CC) --shared -fPIC $(CFLAGS) $(LDFLAGS) $(LIB_SRC) -o $(LINKERNAME) 48 | 49 | all: 50 | @make $(NAME) 51 | 52 | clean: 53 | rm -f $(NAME) $(LINKERNAME) $(OBJ) $(LIB_OBJ) 54 | 55 | re: clean all 56 | -------------------------------------------------------------------------------- /vipe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | vipe - edit pipe 6 | 7 | =head1 SYNOPSIS 8 | 9 | command1 | vipe | command2 10 | 11 | =head1 DESCRIPTION 12 | 13 | vipe allows you to run your editor in the middle of a unix pipeline and 14 | edit the data that is being piped between programs. Your editor will 15 | have the full data being piped from command1 loaded into it, and when you 16 | close it, that data will be piped into command2. 17 | 18 | =head1 ARGUMENTS 19 | 20 | vipe takes an argument --suffix that can be used to provide a file 21 | extension to the temp file generated. This enables editors to provide 22 | syntax highlighting and activate modes. For example, you can call vipe 23 | like 24 | 25 | vipe --suffix csv 26 | 27 | to create a tempfile with .csv extensions which makes Emacs (or your 28 | favorite editor) launch in CSV major mode. 29 | 30 | =head1 ENVIRONMENT VARIABLES 31 | 32 | =over 4 33 | 34 | =item EDITOR 35 | 36 | Editor to use. 37 | 38 | =item VISUAL 39 | 40 | Also supported to determine what editor to use. 41 | 42 | =back 43 | 44 | =head1 AUTHOR 45 | 46 | Copyright 2006 by Joey Hess 47 | 48 | Licensed under the GNU GPL. 49 | 50 | =cut 51 | 52 | use warnings; 53 | use strict; 54 | use File::Temp q{tempfile}; 55 | use Getopt::Long; 56 | 57 | $/=undef; 58 | 59 | my $suffix = ""; 60 | if (! GetOptions("suffix=s" => \$suffix)) { 61 | die "Usage: $0 [--suffix=extension]\n"; 62 | } 63 | $suffix = ".$suffix" if $suffix =~ m/^[^.]/; 64 | 65 | my ($fh, $tmp)=tempfile(UNLINK => 1, SUFFIX => $suffix); 66 | die "cannot create tempfile" unless $fh; 67 | if (! -t STDIN) { 68 | print ($fh ) || die "write temp: $!"; 69 | } 70 | close $fh; 71 | close STDIN; 72 | open(STDIN, "&STDOUT") || die "save stdout: $!"; 74 | close STDOUT; 75 | open(STDOUT, ">/dev/tty") || die "reopen stdout: $!"; 76 | 77 | my @editor="vi"; 78 | if (-x "/usr/bin/editor") { 79 | @editor="/usr/bin/editor"; 80 | } 81 | if (exists $ENV{EDITOR}) { 82 | @editor=split(' ', $ENV{EDITOR}); 83 | } 84 | if (exists $ENV{VISUAL}) { 85 | @editor=split(' ', $ENV{VISUAL}); 86 | } 87 | my $ret=system(@editor, $tmp); 88 | if ($ret != 0) { 89 | die "@editor exited nonzero, aborting\n"; 90 | } 91 | 92 | open (IN, $tmp) || die "$0: cannot read $tmp: $!\n"; 93 | print (OUT ) || die "write failure: $!"; 94 | close IN; 95 | -------------------------------------------------------------------------------- /chronic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | chronic - runs a command quietly unless it fails 6 | 7 | =head1 SYNOPSIS 8 | 9 | chronic [-ev] COMMAND... 10 | 11 | =head1 DESCRIPTION 12 | 13 | chronic runs a command, and arranges for its standard out and standard 14 | error to only be displayed if the command fails (exits nonzero or crashes). 15 | If the command succeeds, any extraneous output will be hidden. 16 | 17 | A common use for chronic is for running a cron job. Rather than 18 | trying to keep the command quiet, and having to deal with mails containing 19 | accidental output when it succeeds, and not verbose enough output when it 20 | fails, you can just run it verbosely always, and use chronic to hide 21 | the successful output. 22 | 23 | 0 1 * * * chronic backup # instead of backup >/dev/null 2>&1 24 | */20 * * * * chronic -ve my_script # verbose for debugging 25 | 26 | =head1 OPTIONS 27 | 28 | =over 4 29 | 30 | =item -v 31 | 32 | Verbose output (distinguishes between STDOUT and STDERR, also reports RETVAL) 33 | 34 | =item -e 35 | 36 | Stderr triggering. Triggers output when stderr output length is non-zero. 37 | Without -e chronic needs non-zero return value to trigger output. 38 | 39 | In this mode, chronic's return value will be C<2> if the command's return 40 | value is C<0> but the command printed to stderr. 41 | 42 | =back 43 | 44 | =head1 AUTHOR 45 | 46 | Copyright 2010 by Joey Hess 47 | 48 | Original concept and "chronic" name by Chuck Houpt. 49 | Code for verbose and stderr trigger by Tomas 'Harvie' Mudrunka 2016. 50 | 51 | Licensed under the GNU GPL version 2 or higher. 52 | 53 | =cut 54 | 55 | use warnings; 56 | use strict; 57 | use IPC::Run qw( start pump finish timeout ); 58 | use Getopt::Std; 59 | 60 | our $opt_e = 0; 61 | our $opt_v = 0; 62 | getopts('ev'); # only looks at options before the COMMAND 63 | 64 | if (! @ARGV) { 65 | die "usage: chronic COMMAND...\n"; 66 | } 67 | 68 | my ($out, $err); 69 | my $h = IPC::Run::start \@ARGV, \*STDIN, \$out, \$err; 70 | $h->finish; 71 | my $ret=$h->full_result; 72 | 73 | if ($ret >> 8) { # child failed 74 | showout(); 75 | exit ($ret >> 8); 76 | } 77 | elsif ($ret != 0) { # child killed by signal 78 | showout(); 79 | exit 1; 80 | } 81 | elsif ($opt_e && (length($err) > 0)) { 82 | showout(); 83 | exit 2; 84 | } 85 | else { 86 | exit 0; 87 | } 88 | 89 | sub showout { 90 | print "STDOUT:\n" if $opt_v; 91 | print STDOUT $out; 92 | print "\nSTDERR:\n" if $opt_v; 93 | STDOUT->flush(); 94 | print STDERR $err; 95 | STDERR->flush(); 96 | print "\nRETVAL: ".($ret >> 8)."\n" if $opt_v; 97 | } 98 | -------------------------------------------------------------------------------- /ifne.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 |
30 | cibervicho@gmail.com 31 |
32 | 33 | Javier 34 | Merino 35 | 36 | 2008-05-01 37 |
38 | 39 | 40 | ifne 41 | 1 42 | moreutils 43 | moreutils 44 | 45 | 46 | 47 | ifne 48 | Run command if the standard input is not empty 49 | 50 | 51 | 52 | 53 | ifne [-n] command 54 | 55 | 56 | 57 | 58 | DESCRIPTION 59 | 60 | ifne runs the following command if and only if 61 | the standard input is not empty. 62 | 63 | 64 | 65 | OPTIONS 66 | 67 | 68 | 69 | 70 | 71 | Reverse operation. Run the command if the standard input is empty. 72 | Note that if the standard input is not empty, it is passed through ifne 73 | in this case. 74 | 75 | 76 | 77 | 78 | 79 | 80 | EXAMPLE 81 | 82 | find . -name core | ifne mail -E 'set escape' -s "Core files found" root 83 | 84 | 85 | 86 | 87 | AUTHOR 88 | 89 | Copyright 2008 by Javier Merino <cibervicho@gmail.com> 90 | Licensed under the GNU GPL 91 | 92 | 93 |
94 | -------------------------------------------------------------------------------- /mispipe.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 |
30 | neroden@fastmail.fm 31 |
32 | 33 | Nathanael 34 | Nerode 35 | 36 | 2006-09-07 37 |
38 | 39 | 40 | mispipe 41 | 1 42 | moreutils 43 | moreutils 44 | 45 | 46 | 47 | mispipe 48 | pipe two commands, returning the exit status of 49 | the first 50 | 51 | 52 | 53 | 54 | mispipe 55 | "command1" 56 | "command2" 57 | 58 | 59 | 60 | 61 | DESCRIPTION 62 | 63 | mispipe pipes two commands 64 | together like the shell does, but unlike piping in the 65 | shell, which returns the exit status of the last command; 66 | when using mispipe, the exit status of the first command 67 | is returned. 68 | 69 | 70 | 71 | Note that some shells, notably bash, 72 | do offer a pipefail option, however, that option does not 73 | behave the same since it makes a failure of any command in 74 | the pipeline be returned, not just the exit status of the 75 | first. 76 | 77 | 78 | 79 | 80 | 81 | EXIT STATUS 82 | 83 | The exit status of the first command. If the process 84 | terminated abnormally (due to a signal), 128 will be added 85 | to its exit status. 86 | 87 | 88 | 89 | 90 | AUTHOR 91 | 92 | Nathanael Nerode 93 | 94 | 95 |
96 | -------------------------------------------------------------------------------- /is_utf8/README.md: -------------------------------------------------------------------------------- 1 | isutf8 is a program and a c library to check if a given file (or stdin) contains only 2 | valid utf-8 sequences. 3 | 4 | # Compiling 5 | 6 | $ make 7 | 8 | # Demo 9 | 10 | $ isutf8 * -v 11 | isutf8: line 1, char 97, byte 96: Expecting bytes in the following ranges: 00..7F C2..F4. 12 | 40 00 40 00 00 00 00 00 C0 01 00 00 00 00 00 00 | @.@............. 13 | ^^ | ^ 14 | 15 | is_utf8.o: line 1, char 66, byte 65: Expecting bytes in the following ranges: 00..7F C2..F4. 16 | 00 40 00 0E 00 0B 00 48 85 F6 48 C7 02 00 00 00 | .@.....H..H..... 17 | ^^ | ^ 18 | 19 | libisutf8.so: line 1, char 153, byte 152: After a first byte of F0, expecting 2nd byte between 90 and BF. 20 | 68 12 20 00 00 00 00 00 F0 01 00 00 00 00 00 00 | h. ............. 21 | ^^^^^ | ^^ 22 | 23 | main.o: line 1, char 76, byte 75: Expecting bytes in the following ranges: 00..7F C2..F4. 24 | 56 41 55 41 54 55 53 48 83 EC 18 48 8B 5C 24 58 | VAUATUSH...H.\$X 25 | ^^ | ^ 26 | 27 | # Test a file 28 | 29 | `isutf8` returns 0 if the file is correctly encoded: 30 | 31 | $ isutf8 main.c 32 | $ echo $? 33 | 0 34 | 35 | Some files here only contain ASCII or correctly encoded UTF8: 36 | 37 | $ isutf8 README.md 38 | $ isutf8 test.sh 39 | 40 | But an ELF is clearly not UTF8, a verbose error is printed: 41 | 42 | $ isutf8 isutf8 43 | isutf8: line 1, char 97, byte 96: Expecting bytes in the following ranges: 00..7F C2..F4. 44 | 45 | `-v` adds some context: 46 | 47 | $ isutf8 -v isutf8 48 | isutf8: line 1, char 97, byte 96: Expecting bytes in the following ranges: 00..7F C2..F4. 49 | 40 00 40 00 00 00 00 00 C0 01 00 00 00 00 00 00 | @.@............. 50 | ^^ | ^ 51 | 52 | # Test stdin 53 | 54 | `isutf8` reads on stdin if no file are given, also note that `bash` 55 | helps a lot with the `$''` syntax allowing you to write and test hexadecimal: 56 | 57 | $ echo $'\xe9' | isutf8 58 | (standard input): line 1, char 0, byte 0: After a first byte between E1 and EC, expecting two following bytes. 59 | 60 | $ echo "Hellö world" | iconv -f utf8 -t latin1 | isutf8 61 | (standard input): line 1, char 4, byte 4: Expecting bytes in the following ranges: 00..7F C2..F4. 62 | 63 | # Find UTF8 or non-UTF8 files 64 | 65 | As `isutf8` can take multiple arguments it's easy classify 66 | UTF8-compatible versus non UTF8-compatible files: 67 | 68 | List non-UTF8 compatible files: 69 | 70 | $ isutf8 --list * 71 | isutf8 72 | is_utf8.o 73 | libisutf8.so 74 | main.o 75 | 76 | List UTF8-compatible files: 77 | 78 | $ isutf8 --list --invert * 79 | COPYRIGHT 80 | is_utf8.c 81 | is_utf8.h 82 | main.c 83 | Makefile 84 | README.md 85 | test.sh 86 | -------------------------------------------------------------------------------- /pee.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* Licensed under the GPL 10 | * Copyright (c) Miek Gieben, 2006 11 | */ 12 | 13 | /* like tee(1), but then connect to other programs using 14 | * pipes _and_ output to standard output 15 | */ 16 | 17 | int 18 | close_pipes(FILE **p, size_t i) 19 | { 20 | int ret=EXIT_SUCCESS; 21 | size_t j; 22 | for (j = 0; j < i; j++) { 23 | int r = pclose(p[j]); 24 | if (WIFEXITED(r)) 25 | ret |= WEXITSTATUS(r); 26 | else 27 | ret |= 1; 28 | } 29 | return ret; 30 | } 31 | 32 | int 33 | main(int argc, char **argv) { 34 | int ignore_write_error = 1; 35 | int ignore_sigpipe = 1; 36 | size_t i, r; 37 | FILE **pipes; 38 | int *inactive_pipe; 39 | int inactive_pipes = 0; 40 | char buf[BUFSIZ]; 41 | 42 | while(argc > 1) { 43 | if (!strcmp(argv[1], "--no-ignore-sigpipe")) { 44 | argc--, argv++; 45 | ignore_sigpipe = 0; 46 | continue; 47 | } else if (!strcmp(argv[1], "--ignore-sigpipe")) { 48 | argc--, argv++; 49 | ignore_sigpipe = 1; 50 | continue; 51 | } else if (!strcmp(argv[1], "--no-ignore-write-errors")) { 52 | argc--, argv++; 53 | ignore_write_error = 0; 54 | continue; 55 | } else if (!strcmp(argv[1], "--ignore-write-errors")) { 56 | argc--, argv++; 57 | ignore_write_error = 1; 58 | continue; 59 | } 60 | break; 61 | } 62 | 63 | if (ignore_sigpipe && (signal(SIGPIPE, SIG_IGN) == SIG_ERR)) { 64 | fprintf(stderr, "Unable to ignore SIGPIPE\n"); 65 | exit(EXIT_FAILURE); 66 | } 67 | 68 | pipes = malloc(((argc - 1) * sizeof *pipes)); 69 | inactive_pipe = calloc((argc - 1), (sizeof *inactive_pipe)); 70 | if (!pipes || !inactive_pipe) 71 | exit(EXIT_FAILURE); 72 | 73 | for (i = 1; i < argc; i++) { 74 | pipes[i - 1] = popen(argv[i], "w"); 75 | if (!pipes[i - 1]) { 76 | fprintf(stderr, "Can not open pipe to '%s\'\n", argv[i]); 77 | close_pipes(pipes, argc); 78 | 79 | exit(EXIT_FAILURE); 80 | } 81 | 82 | setbuf(pipes[i - 1], NULL); 83 | } 84 | argc--; 85 | 86 | for (;;) { 87 | r = read(STDIN_FILENO, buf, BUFSIZ); 88 | 89 | /* Interrupted by signal? Try again. */ 90 | if (r == -1 && errno == EINTR) 91 | continue; 92 | 93 | /* Other error or EOF. */ 94 | if (r < 1) 95 | break; 96 | 97 | for(i = 0; i < argc; i++) { 98 | if (inactive_pipe[i]) 99 | continue; 100 | 101 | if (fwrite(buf, sizeof(char), r, pipes[i]) == r) 102 | continue; 103 | 104 | inactive_pipes++; 105 | 106 | if (!ignore_write_error) 107 | fprintf(stderr, "Write error to `%s\'\n", 108 | argv[i + 1]); 109 | 110 | if (!ignore_write_error || (inactive_pipes == argc)) { 111 | close_pipes(pipes, argc); 112 | exit(EXIT_FAILURE); 113 | } 114 | 115 | inactive_pipe[i] = 1; 116 | } 117 | } 118 | exit(close_pipes(pipes, argc)); 119 | } 120 | -------------------------------------------------------------------------------- /zrun: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | zrun - automatically uncompress arguments to command 6 | 7 | =head1 SYNOPSIS 8 | 9 | zrun command file.gz [...] 10 | 11 | =head1 DESCRIPTION 12 | 13 | Prefixing a shell command with "zrun" causes any compressed files that are 14 | arguments of the command to be transparently uncompressed to temp files 15 | (not pipes) and the uncompressed files fed to the command. 16 | 17 | This is a quick way to run a command that does not itself support 18 | compressed files, without manually uncompressing the files. 19 | 20 | The following compression types are supported: gz bz2 Z xz lzma lzo zstd 21 | 22 | If zrun is linked to some name beginning with z, like zprog, and the link is 23 | executed, this is equivalent to executing "zrun prog". 24 | 25 | =head1 BUGS 26 | 27 | Modifications to the uncompressed temporary file are not fed back into the 28 | input file, so using this as a quick way to make an editor support 29 | compressed files won't work. 30 | 31 | =head1 AUTHOR 32 | 33 | Copyright 2006 by Chung-chieh Shan 34 | 35 | =cut 36 | 37 | use warnings; 38 | use strict; 39 | use IO::Handle; 40 | use File::Spec; 41 | use File::Temp qw{tempfile}; 42 | 43 | my $program; 44 | 45 | if ($0 =~ m{(?:^|/)z([^/]+)$} && $1 ne 'run') { 46 | $program = $1; 47 | if (! @ARGV) { 48 | die "Usage: z$1 \nEquivalent to: zrun $1 \n"; 49 | } 50 | } 51 | else { 52 | $program = shift; 53 | if (! @ARGV) { 54 | die "Usage: zrun \n"; 55 | } 56 | } 57 | 58 | my @argument; 59 | my %child; 60 | foreach my $argument (@ARGV) { 61 | if ($argument =~ m{^(.*/)?([^/]*)\.(gz|Z|bz2|xz|lzo|lzma|zst)$}s) { 62 | my $suffix = "-$2"; 63 | my @preprocess = $3 eq "bz2" ? qw(bzip2 -d -c) : 64 | $3 eq "xz" ? qw(xz -d -c) : 65 | $3 eq "lzo" ? qw(lzop -d -c) : 66 | $3 eq "lzma" ? qw(lzma -d -c) : 67 | $3 eq "zst" ? qw(zstd -d -c) : qw(gzip -d -c); 68 | 69 | my ($fh, $tmpname) = tempfile(SUFFIX => $suffix, 70 | DIR => File::Spec->tmpdir, UNLINK => 1) 71 | or die "zrun: cannot create temporary file: $!\n"; 72 | 73 | if (my $child = fork) { 74 | $child{$child} = $argument; 75 | $argument = $tmpname; 76 | } 77 | elsif (defined $child) { 78 | STDOUT->fdopen($fh, "w"); 79 | exec @preprocess, $argument; 80 | } 81 | else { 82 | die "zrun: cannot fork to handle $argument: $!\n"; 83 | } 84 | } 85 | push @argument, $argument; 86 | } 87 | 88 | while (%child and (my $pid = wait) != -1) { 89 | if (defined(my $argument = delete $child{$pid})) { 90 | if ($? & 255) { 91 | die "zrun: preprocessing for $argument terminated abnormally: $?\n"; 92 | } 93 | elsif (my $code = $? >> 8) { 94 | die "zrun: preprocessing for $argument terminated with code $code\n"; 95 | } 96 | } 97 | } 98 | 99 | my $status = system $program ($program, @argument); 100 | if ($status & 255) { 101 | die "zrun: $program terminated abnormally: $?\n"; 102 | } 103 | else { 104 | my $code = $? >> 8; 105 | exit $code; 106 | } 107 | -------------------------------------------------------------------------------- /sponge.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | Joey 32 | Hess 33 | 34 | 2006-02-19 35 | 36 | 37 | 38 | sponge 39 | 1 40 | moreutils 41 | moreutils 42 | 43 | 44 | 45 | sponge 46 | soak up standard input and write to a file 47 | 48 | 49 | 50 | 51 | sed '...' file | grep '...' | sponge [-a] file 52 | 53 | 54 | 55 | 56 | DESCRIPTION 57 | 58 | sponge reads standard input and 59 | writes it out to the specified file. Unlike a shell 60 | redirect, sponge soaks up all its input before 61 | writing the output file. This allows constructing 62 | pipelines that read from and write to 63 | the same file. 64 | 65 | 66 | sponge preserves the 67 | permissions of the output file 68 | if it already exists. 69 | 70 | 71 | When possible, sponge creates or updates the 72 | output file atomically by renaming a temp 73 | file into place. (This cannot be done 74 | if TMPDIR is not in the same filesystem.) 75 | 76 | 77 | If the output file is a special file or symlink, 78 | the data will be written to it, non-atomically. 79 | 80 | 81 | If no file is specified, sponge outputs to 82 | stdout. 83 | 84 | 85 | 86 | 87 | OPTIONS 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | Replace the file 96 | with a new file that contains 97 | the file's original content, 98 | with the standard input 99 | appended to it. This is done 100 | atomically when possible. 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | AUTHOR 110 | 111 | Colin Watson and Tollef Fog Heen 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /ifne.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2008 Javier Merino 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 12 | * Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | * 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define streq(a, b) (!strcmp((a), (b))) 29 | 30 | static void stdin_to_stream(char *buf, ssize_t r, FILE *outf) { 31 | while (r > 0) { 32 | if (fwrite(buf, r*sizeof(char), 1, outf) < 1) { 33 | fprintf(stderr, "Write error\n"); 34 | exit(EXIT_FAILURE); 35 | } 36 | r = read(0, buf, BUFSIZ*sizeof(char)); 37 | } 38 | if (r == -1) { 39 | perror("read"); 40 | exit(EXIT_FAILURE); 41 | } 42 | } 43 | 44 | int main(int argc, char **argv) { 45 | ssize_t r; 46 | int run_if_empty; 47 | char **argv_exec; 48 | int fds[2]; 49 | int child_status; 50 | pid_t child_pid; 51 | char buf[BUFSIZ]; 52 | FILE *outf; 53 | 54 | if ((argc < 2) || ((argc == 2) && streq(argv[1], "-n"))) { 55 | fprintf(stderr, "Usage: ifne [-n] command [args]\n"); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | if (streq(argv[1], "-n")) { 60 | run_if_empty = 1; 61 | argv_exec = &argv[2]; 62 | } else { 63 | run_if_empty = 0; 64 | argv_exec = &argv[1]; 65 | } 66 | 67 | r = read(0, buf, BUFSIZ*sizeof(char)); 68 | 69 | if ((r == 0) && !run_if_empty) 70 | return EXIT_SUCCESS; 71 | else if (r == -1) { 72 | perror("read"); 73 | return EXIT_FAILURE; 74 | } 75 | 76 | if (pipe(fds)) { 77 | perror("pipe"); 78 | return EXIT_FAILURE; 79 | } 80 | 81 | if (r && run_if_empty) { 82 | /* don't run the subcommand if we read something from stdin and -n was set */ 83 | /* But write stdin to stdout so ifne -n can be piped without sucking the stream */ 84 | stdin_to_stream(buf, r, stdout); 85 | return EXIT_SUCCESS; 86 | } 87 | 88 | child_pid = fork(); 89 | if (!child_pid) { 90 | /* child process: rebind stdin and exec the subcommand */ 91 | close(fds[1]); 92 | if (dup2(fds[0], 0)) { 93 | perror("dup2"); 94 | return EXIT_FAILURE; 95 | } 96 | 97 | execvp(*argv_exec, argv_exec); 98 | perror(*argv_exec); 99 | close(fds[0]); 100 | return EXIT_FAILURE; 101 | } else if (child_pid == -1) { 102 | perror("fork"); 103 | return EXIT_FAILURE; 104 | } 105 | 106 | /* Parent: write stdin to fds[1] */ 107 | close(fds[0]); 108 | outf = fdopen(fds[1], "w"); 109 | if (! outf) { 110 | perror("fdopen"); 111 | exit(1); 112 | } 113 | 114 | stdin_to_stream(buf, r, outf); 115 | fclose(outf); 116 | 117 | if (waitpid(child_pid, &child_status, 0) != child_pid) { 118 | perror("waitpid"); 119 | return EXIT_FAILURE; 120 | } 121 | if (WIFEXITED(child_status)) { 122 | return (WEXITSTATUS(child_status)); 123 | } else if (WIFSIGNALED(child_status)) { 124 | raise(WTERMSIG(child_status)); 125 | return EXIT_FAILURE; 126 | } 127 | 128 | return EXIT_FAILURE; 129 | } 130 | -------------------------------------------------------------------------------- /combine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | combine - combine sets of lines from two files using boolean operations 6 | 7 | =head1 SYNOPSIS 8 | 9 | combine file1 and file2 10 | 11 | combine file1 not file2 12 | 13 | combine file1 or file2 14 | 15 | combine file1 xor file2 16 | 17 | _ file1 and file2 _ 18 | 19 | _ file1 not file2 _ 20 | 21 | _ file1 or file2 _ 22 | 23 | _ file1 xor file2 _ 24 | 25 | =head1 DESCRIPTION 26 | 27 | B combines the lines in two files. Depending on the boolean 28 | operation specified, the contents will be combined in different ways: 29 | 30 | =over 4 31 | 32 | =item and 33 | 34 | Outputs lines that are in file1 if they are also present in file2. 35 | 36 | =item not 37 | 38 | Outputs lines that are in file1 but not in file2. 39 | 40 | =item or 41 | 42 | Outputs lines that are in file1 or file2. 43 | 44 | =item xor 45 | 46 | Outputs lines that are in either file1 or file2, but not in both files. 47 | 48 | =back 49 | 50 | "-" can be specified for either file to read stdin for that file. 51 | 52 | The input files need not be sorted, and the lines are output in the order 53 | they occur in file1 (followed by the order they occur in file2 for the two 54 | "or" operations). Bear in mind that this means that the operations are not 55 | commutative; "a and b" will not necessarily be the same as "b and a". To 56 | obtain commutative behavior sort and uniq the result. 57 | 58 | Note that this program can be installed as "_" to allow for the syntactic 59 | sugar shown in the latter half of the synopsis (similar to the test/[ 60 | command). It is not currently installed as "_" by default, but you can 61 | alias it to that if you like. 62 | 63 | =head1 SEE ALSO 64 | 65 | join(1) 66 | 67 | =head1 AUTHOR 68 | 69 | Copyright 2006 by Joey Hess 70 | 71 | Licensed under the GNU GPL. 72 | 73 | =cut 74 | 75 | use warnings; 76 | use strict; 77 | 78 | sub filemap { 79 | my $file=shift; 80 | my $sub=shift; 81 | 82 | open (IN, $file) || die "$file: $!\n"; 83 | while () { 84 | chomp; 85 | $sub->(); 86 | } 87 | close IN; 88 | } 89 | 90 | sub hashify { 91 | my $file=shift; 92 | 93 | my %seen; 94 | filemap $file, sub { $seen{$_}++ }; 95 | return \%seen; 96 | } 97 | 98 | sub compare_or { 99 | my ($file1, $file2) = @_; 100 | 101 | filemap $file1, sub { print "$_\n" }; 102 | filemap $file2, sub { print "$_\n" }; 103 | } 104 | 105 | sub compare_xor { 106 | my ($file1, $file2) = @_; 107 | 108 | my (@lines2, %seen2); 109 | filemap $file2, 110 | sub { 111 | push @lines2, $_; 112 | $seen2{$_} = 1; 113 | }; 114 | 115 | # Print all lines in file1 that are not in file2, 116 | # and mark lines that are in both files by setting 117 | # their value in %seen2 to 0. 118 | filemap $file1, 119 | sub { 120 | if (exists $seen2{$_}) { 121 | $seen2{$_} = 0; 122 | } 123 | else { 124 | print "$_\n"; 125 | } 126 | }; 127 | 128 | # Print all lines that are in file2 but not in file1. 129 | # The value of these lines in seen2 is set to 1. 130 | foreach (@lines2) { 131 | print "$_\n" if $seen2{$_}; 132 | } 133 | } 134 | 135 | sub compare_not { 136 | my ($file1, $file2) = @_; 137 | 138 | my $seen=hashify($file2); 139 | filemap $file1, sub { print "$_\n" unless $seen->{$_} }; 140 | } 141 | 142 | sub compare_and { 143 | my ($file1, $file2) = @_; 144 | 145 | my $seen=hashify($file2); 146 | filemap $file1, sub { print "$_\n" if $seen->{$_} }; 147 | } 148 | 149 | if (@ARGV >= 4 && $ARGV[3] eq "_") { 150 | delete $ARGV[3]; 151 | } 152 | 153 | if (@ARGV != 3) { 154 | die "Usage: combine file1 OP file2\n"; 155 | } 156 | 157 | my $file1=shift; 158 | my $op=lc shift; 159 | my $file2=shift; 160 | 161 | if ($::{"compare_$op"}) { 162 | no strict 'refs'; 163 | "compare_$op"->($file1, $file2); 164 | } 165 | else { 166 | die "unknown operation, $op\n"; 167 | } 168 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Source: Contributed by many folks. 3 | 4 | Files: * 5 | Copyright: 2006-2015 Joey Hess 6 | License: GPL-2+ 7 | 8 | Files: is_utf8/* 9 | Copyright: 2016 Julien Palard 10 | License: BSD-2-Clause 11 | 12 | Files: sponge.* 13 | Copyright: 2006 Tollef Fog Heen 14 | License: GPL-2 15 | 16 | Files: ifdata.c 17 | Copyright: 2002 Benjamin BAYART 18 | License: GPL-2+ 19 | 20 | Files: pee.c 21 | Copyright: 2006 Miek Gieben 22 | License: GPL-2+ 23 | 24 | Files: zrun 25 | Copyright: 2006 Chung-chieh Shan 26 | License: GPL-2+ 27 | 28 | Files: mispipe.c 29 | Copyright: 2004 Nathanael Nerode 30 | License: GPL-2+ or Expat 31 | 32 | Files: lckdo.c lckdo.docbook 33 | Copyright: Michael Tokarev 34 | License: other 35 | Public domain 36 | 37 | Files: ifne.c ifne.docbook 38 | Copyright: 2008 Javier Merino 39 | License: GPL-2+ 40 | 41 | Files: parallel.c 42 | Copyright: 2008 Tollef Fog Heen 43 | License: GPL-2 44 | 45 | Files: errno.c errno.docbook 46 | Copyright: 2012 Lars Wirzenius 47 | License: GPL-2+ 48 | 49 | Files: physmem.c 50 | Copyright: 2000, 2001, 2003, 2005, 2006 Free Software Foundation, Inc. 51 | License: GPL-2+ 52 | 53 | License: GPL-2 54 | The full text of the GPL is distributed as COPYING in moreutils's source, 55 | and is distributed in /usr/share/common-licenses/GPL-2 on Debian systems. 56 | 57 | License: GPL-2+ 58 | The full text of the GPL is distributed as COPYING in moreutils's source, 59 | and is distributed in /usr/share/common-licenses/GPL-2 on Debian systems. 60 | 61 | License: Expat 62 | * Permission is hereby granted, free of charge, to any person obtaining a 63 | * copy of this software and associated documentation files (the "Software"), 64 | * to deal in the Software without restriction, including without limitation 65 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 66 | * and/or sell copies of the Software, and to permit persons to whom the 67 | * Software is furnished to do so, subject to the following conditions: 68 | * 69 | * The above copyright notice and this permission notice shall be included in 70 | * all copies or substantial portions of the Software. 71 | * 72 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 73 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 74 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 75 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 76 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 77 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 78 | * THE SOFTWARE. 79 | 80 | License: BSD-2-clause 81 | # All rights reserved. 82 | # 83 | # Redistribution and use in source and binary forms, with or without 84 | # modification, are permitted provided that the following conditions 85 | # are met: 86 | # 1. Redistributions of source code must retain the above copyright 87 | # notice, this list of conditions and the following disclaimer. 88 | # 2. Redistributions in binary form must reproduce the above copyright 89 | # notice, this list of conditions and the following disclaimer in the 90 | # documentation and/or other materials provided with the distribution. 91 | # 92 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 93 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 94 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 95 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 96 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 97 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 98 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 99 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 100 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 101 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 102 | -------------------------------------------------------------------------------- /pee.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 |
30 | id@joeyh.name 31 |
32 | 33 | Joey 34 | Hess 35 | 36 | 2016-12-20 37 |
38 | 39 | 40 | pee 41 | 1 42 | moreutils 43 | moreutils 44 | 45 | 46 | 47 | pee 48 | tee standard input to pipes 49 | 50 | 51 | 52 | 53 | pee 54 | --[no-]ignore-sigpipe 55 | --[no-]ignore-write-errors 56 | 57 | "command" 58 | 59 | 60 | 61 | 62 | 63 | DESCRIPTION 64 | 65 | pee is like tee 66 | but for pipes. Each command is run and fed a copy of the 67 | standard input. The output of all commands is sent to 68 | stdout. 69 | 70 | Note that while this is similar to 71 | tee, a copy of the input is not sent 72 | to stdout, like tee does. If that is desired, use 73 | pee cat ... 74 | 75 | 76 | 77 | OPTIONS 78 | 79 | 80 | 81 | 82 | 83 | 84 | Do (not) ignore SIGPIPE. Any command started 85 | by pee might cause a SIGPIPE 86 | when it exists. If you ignore SIGPIPE, you 87 | probably also want to ignore write errors (see 88 | below). Ignoring SIGPIPE is the default 89 | behaviour. 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Do (not) ignore write errors. When a command 98 | started by pee is no more 99 | accepting data via the pipe between itself and 100 | pee, a write error occurs in 101 | pee. If this error is not 102 | ignored, pee is going to 103 | terminate all child processes and exists. Ignoring 104 | write errors is the default behaviour. 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | SEE ALSO 113 | 114 | 115 | 116 | tee1 117 | , 118 | 119 | pipe7 120 | 121 | 122 | 123 | 124 | 125 | 126 | AUTHOR 127 | 128 | Miek Gieben 129 | 130 | 131 |
132 | -------------------------------------------------------------------------------- /lckdo.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 13 | 14 | 15 | 16 |
17 | mjt@tls.msk.ru 18 |
19 | 20 | Michael 21 | Tokarev 22 | 23 | 2007-08-15 24 |
25 | 26 | 27 | lckdo 28 | 1 29 | moreutils 30 | moreutils 31 | 32 | 33 | 34 | lckdo 35 | run a program with a lock held 36 | 37 | 38 | 39 | 40 | lckdo 41 | options 42 | lockfile 43 | program 44 | arguments 45 | 46 | 47 | 48 | 49 | DESCRIPTION 50 | 51 | lckdo runs a program with a lock 52 | held, in order to prevent multiple processes from running in 53 | parallel. Use just like nice or 54 | nohup. 55 | 56 | Now that util-linux contains a similar command 57 | named flock, lckdo is deprecated, 58 | and will be removed from some future version of moreutils. 59 | 60 | 61 | 62 | 63 | 64 | OPTIONS 65 | 66 | 67 | 68 | 69 | 70 | 71 | If the lock is already held by another process, 72 | wait for it to complete instead of failing 73 | immediately. 74 | 75 | 76 | 77 | 78 | 79 | 80 | The same as -w but wait not more than sec 81 | seconds. 82 | 83 | 84 | 85 | 86 | 87 | 88 | Execute the program directly without forking and 89 | waiting (keeps an extra file descriptor open). 90 | 91 | 92 | 93 | 94 | 95 | 96 | Set the file descriptor number to keep open when 97 | exec()ing (implies -e). 98 | 99 | 100 | 101 | 102 | 103 | 104 | Do not create the lock file if it does not 105 | exist. 106 | 107 | 108 | 109 | 110 | 111 | 112 | Produce no output if lock is already held. 113 | 114 | 115 | 116 | 117 | 118 | 119 | Lock in shared (read) mode. 120 | 121 | 122 | 123 | 124 | 125 | 126 | Lock in exclusive (write) mode (default). 127 | 128 | 129 | 130 | 131 | 132 | 133 | Test for lock existence. 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | EXIT STATUS 143 | 144 | If the lock was successfully acquired, the return value is that 145 | of the program invoked by lckdo. If the lock 146 | couldn't be acquired, EX_TEMPFAIL is returned. If there was a problem 147 | opening/creating or locking the lock file, EX_CANTCREAT or EX_OSERR 148 | will be returned. 149 | 150 | 151 | 152 | 153 | AUTHOR 154 | 155 | Michael Tokarev 156 | 157 | 158 | 159 |
160 | -------------------------------------------------------------------------------- /errno.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 |
30 | liw@liw.fi 31 |
32 | 33 | Lars 34 | Wirzenius 35 | 36 | 2012-06-05 37 |
38 | 39 | 40 | errno 41 | 1 42 | moreutils 43 | moreutils 44 | 45 | 46 | 47 | errno 48 | look up errno names and descriptions 49 | 50 | 51 | 52 | 53 | errno 54 | name-or-code 55 | 56 | 57 | errno 58 | -ls 59 | --list 60 | 61 | 62 | errno 63 | -s 64 | --search 65 | word 66 | 67 | 68 | errno 69 | -S 70 | --search-all-locales 71 | word 72 | 73 | 74 | 75 | 76 | DESCRIPTION 77 | 78 | errno looks up errno macro names, 79 | errno codes, and the corresponding descriptions. For example, 80 | if given ENOENT on a Linux system, it 81 | prints out the code 2 and the description "No such file or directory". 82 | If given the code 2, it prints ENOENT 83 | and the same description. 84 | 85 | 86 | 87 | 88 | OPTIONS 89 | 90 | 91 | 92 | 93 | 94 | 95 | List all errno values. 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Search for errors whose description contains 104 | all the given words (case-insensitive). 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | Like , but searches all 113 | installed locales. 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | AUTHOR 122 | 123 | 124 | Lars Wirzenius 125 | 126 | 127 | 128 | 129 | SEE ALSO 130 | 131 | 132 | 133 | errno3 134 | 135 | 136 | 137 | 138 |
139 | -------------------------------------------------------------------------------- /isutf8.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | Lars 32 | Wirzenius 33 | liw@iki.fi 34 | 35 | 36 | Julien 37 | Palard 38 | julien@palard.fr 39 | 40 | 41 | 42 | 43 | 44 | isutf8 45 | 1 46 | moreutils 47 | moreutils 48 | 49 | 50 | 51 | isutf8 52 | check whether files are valid UTF-8 53 | 54 | 55 | 56 | 57 | isutf8 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | file 66 | 67 | 68 | 69 | 70 | 71 | DESCRIPTION 72 | 73 | isutf8 checks whether files are 74 | syntactically valid UTF-8. Input is either files named on the 75 | command line, or the standard input. Notices about files with 76 | invalid UTF-8 are printed to standard output. 77 | 78 | 79 | 80 | 81 | OPTIONS 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | Print out a help summary. 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Don't print messages telling which files are 98 | invalid UTF-8, merely indicate it with the exit 99 | status. 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | Print only the names of files containing invalid 108 | UTF-8. 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | Invert the selection: list UTF-8 compatible 117 | files. 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Also print an hexdump-like view of the error and some 126 | context. 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | EXIT STATUS 136 | 137 | If the file is valid UTF-8, the exit status is zero. 138 | If the file is not valid UTF-8, or there is some 139 | error, the exit status is non-zero. 140 | 141 | 142 | 143 | 144 | AUTHOR 145 | 146 | 147 | Lars Wirzenius, Julien Palard 148 | 149 | 150 | 151 | 152 | SEE ALSO 153 | 154 | 155 | 156 | utf87 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /parallel.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 12 | 13 | 14 | 15 |
16 | id@joeyh.name 17 |
18 | 19 | Joey 20 | Hess 21 | 22 | 2009-07-02 23 |
24 | 25 | 26 | parallel 27 | 1 28 | moreutils 29 | moreutils 30 | 31 | 32 | 33 | parallel 34 | run programs in parallel 35 | 36 | 37 | 38 | 39 | parallel 40 | options 41 | command 42 | -- 43 | argument ... 44 | 45 | 46 | parallel 47 | options 48 | -- 49 | command ... 50 | 51 | 52 | 53 | 54 | DESCRIPTION 55 | 56 | parallel runs the specified command, 57 | passing it a single one of the specified arguments. This is 58 | repeated for each argument. Jobs may be run in 59 | parallel. The default is to run one job per CPU. 60 | 61 | If no command is specified before the --, 62 | the commands after it are instead run in parallel. 63 | 64 | 65 | 66 | 67 | OPTIONS 68 | 69 | 70 | 71 | 72 | 73 | 74 | Use to limit the number of jobs 75 | that are run at the same time. 76 | 77 | 78 | 79 | 80 | 81 | 82 | Wait as needed to avoid starting 83 | new jobs when the system's load average 84 | is not below the specified limit. 85 | 86 | 87 | 88 | 89 | 90 | 91 | Normally the command is passed the 92 | argument at the end of its command line. With 93 | this option, any instances of "{}" in 94 | the command are replaced with the argument. 95 | 96 | 97 | 98 | 99 | 100 | 101 | Number of arguments to pass to a 102 | command at a time. Default is 1. 103 | Incompatible with -i 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | EXAMPLE 113 | 114 | 115 | parallel sh -c "echo hi; sleep 2; echo bye" -- 1 2 3 116 | 117 | 118 | This runs three subshells that each print a message, delay, 119 | and print another message. If your system has multiple 120 | CPUs, parallel will run some of the jobs in parallel, 121 | which should be clear from the order the messages are 122 | output. 123 | 124 | 125 | 126 | parallel -j 3 ufraw -o processed -- *.NEF 127 | 128 | 129 | This runs three ufraw processes at the same time until 130 | all of the NEF files have been processed. 131 | 132 | 133 | 134 | parallel -j 3 -- ls df "echo hi" 135 | 136 | 137 | This runs three independent commands in parallel. 138 | 139 | 140 | 141 | 142 | EXIT STATUS 143 | 144 | 145 | Its exit status is the combination of the exit statuses of each 146 | command ran, ORed together. (Thus, if any one command 147 | exits nonzero, parallel as a whole will exit nonzero.) 148 | 149 | 150 | 151 | 152 | NOTES 153 | 154 | 155 | All output to stdout and stderr is serialised through a 156 | corresponding internal pipe, in order to prevent annoying 157 | concurrent output behaviour. Note that serialisation is not 158 | done on any other file descriptors and file position based 159 | access to a nonstandard file descriptor might have unexpected 160 | results. 161 | 162 | 163 | 164 | 165 | 166 | AUTHOR 167 | 168 | Tollef Fog Heen 169 | 170 | 171 | 172 |
173 | -------------------------------------------------------------------------------- /ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | ts - timestamp input 6 | 7 | =head1 SYNOPSIS 8 | 9 | ts [-r] [-i | -s] [-m] [format] 10 | 11 | =head1 DESCRIPTION 12 | 13 | ts adds a timestamp to the beginning of each line of input. 14 | 15 | The optional format parameter controls how the timestamp is formatted, 16 | as used by L. The default format is "%b %d %H:%M:%S". In 17 | addition to the regular strftime conversion specifications, 18 | "%.S" and "%.s" and "%.T" 19 | are like "%S" and "%s" and "%T", but provide subsecond resolution 20 | (ie, "30.00001" and "1301682593.00001" and "1:15:30.00001"). 21 | 22 | If the -r switch is passed, it instead converts existing timestamps in 23 | the input to relative times, such as "15m5s ago". Many common timestamp 24 | formats are supported. Note that the Time::Duration and Date::Parse perl 25 | modules are required for this mode to work. Currently, converting localized 26 | dates is not supported. 27 | 28 | If both -r and a format is passed, the existing timestamps are 29 | converted to the specified format. 30 | 31 | If the -i or -s switch is passed, ts reports incremental timestamps instead of 32 | absolute ones. The default format changes to "%H:%M:%S", and "%.S" and "%.s" can 33 | be used as well. In case of -i, every timestamp will be the time elapsed since 34 | the last timestamp. In case of -s, the time elapsed since start of the program 35 | is used. 36 | 37 | The -m switch makes the system's monotonic clock be used. 38 | 39 | =head1 ENVIRONMENT 40 | 41 | The standard TZ environment variable controls what time zone dates 42 | are assumed to be in, if a timezone is not specified as part of the date. 43 | 44 | =head1 AUTHOR 45 | 46 | Copyright 2006 by Joey Hess 47 | 48 | Licensed under the GNU GPL. 49 | 50 | =cut 51 | 52 | use warnings; 53 | use strict; 54 | use POSIX q{strftime}; 55 | no warnings 'utf8'; 56 | 57 | $|=1; 58 | 59 | my $rel=0; 60 | my $inc=0; 61 | my $sincestart=0; 62 | my $mono=0; 63 | use Getopt::Long; 64 | GetOptions( 65 | "r" => \$rel, 66 | "i" => sub { $inc=1; $sincestart=0 }, 67 | "s" => sub { $inc=0; $sincestart=1 }, 68 | "m" => \$mono 69 | ) && @ARGV <= 1 or die "usage: ts [-r] [-i | -s] [-m] [format]\n"; 70 | 71 | if ($rel) { 72 | eval q{ 73 | use Date::Parse; 74 | use Time::Duration; 75 | }; 76 | die $@ if $@; 77 | } 78 | 79 | my $use_format=@ARGV; 80 | my $format="%b %d %H:%M:%S"; 81 | if ($inc || $sincestart) { 82 | $format="%H:%M:%S"; 83 | $ENV{TZ}='GMT'; 84 | } 85 | $format=shift if @ARGV; 86 | 87 | # For subsecond resolution, Time::HiRes is needed. 88 | my $hires=0; 89 | if ($format=~/\%\.[SsT]/ || $mono) { 90 | require Time::HiRes; 91 | use Time::HiRes qw(CLOCK_MONOTONIC); 92 | $hires=1; 93 | } 94 | 95 | my $lastseconds = 0; 96 | my $lastmicroseconds = 0; 97 | my $monodelta; 98 | 99 | if ($mono) { 100 | my $raw_time = Time::HiRes::clock_gettime(CLOCK_MONOTONIC); 101 | $lastseconds = time; 102 | $lastmicroseconds = int(1000000 * ($raw_time - int($raw_time))); 103 | $monodelta = $lastseconds - int($raw_time); 104 | } 105 | elsif ($hires) { 106 | ($lastseconds, $lastmicroseconds) = Time::HiRes::gettimeofday(); 107 | } 108 | else { 109 | $lastseconds = time; 110 | } 111 | 112 | 113 | while () { 114 | if (! $rel) { 115 | if ($hires) { 116 | my $f=$format; 117 | my $seconds; 118 | my $microseconds; 119 | if ($mono) { 120 | my $raw_time = 121 | Time::HiRes::clock_gettime(CLOCK_MONOTONIC) + 122 | $monodelta; 123 | $seconds = int($raw_time); 124 | $microseconds = int(1000000 * ($raw_time - $seconds)); 125 | } 126 | else { 127 | ($seconds, $microseconds) = Time::HiRes::gettimeofday(); 128 | } 129 | 130 | if ($inc || $sincestart) { 131 | my $deltaseconds = $seconds - $lastseconds; 132 | my $deltamicroseconds = $microseconds - $lastmicroseconds; 133 | if ($deltamicroseconds < 0) { 134 | $deltaseconds -= 1; 135 | $deltamicroseconds += 1000000; 136 | } 137 | if ($inc) { 138 | $lastseconds = $seconds; 139 | $lastmicroseconds = $microseconds; 140 | } 141 | $seconds = $deltaseconds; 142 | $microseconds = $deltamicroseconds; 143 | } 144 | my $s=sprintf("%06i", $microseconds); 145 | $f=~s/\%\.([SsT])/%$1.$s/g; 146 | print strftime($f, localtime($seconds)); 147 | } 148 | else { 149 | if ($inc || $sincestart) { 150 | my $seconds = time; 151 | my $deltaseconds = $seconds - $lastseconds; 152 | if ($inc) { 153 | $lastseconds = $seconds; 154 | } 155 | print strftime($format, localtime($deltaseconds)); 156 | } 157 | else { 158 | print strftime($format, localtime); 159 | } 160 | } 161 | print " ".$_; 162 | } 163 | else { 164 | s{\b( 165 | \d\d[-\s\/]\w\w\w # 21 dec 17:05 166 | (?:\/\d\d+)? # 21 dec/93 17:05 167 | [\s:]\d\d:\d\d # (time part of above) 168 | (?::\d\d)? # (optional seconds) 169 | (?:\s+[+-]\d\d\d\d)? # (optional timezone) 170 | | 171 | \w{3}\s+\d{1,2}\s+\d\d:\d\d:\d\d # syslog form 172 | | 173 | \d\d\d\d[-:]\d\d[-:]\d\dT\d\d:\d\d:\d\d.\d+Z? # ISO-8601 174 | | 175 | (?:\w\w\w,?\s+)? # (optional Day) 176 | \d+\s+\w\w\w\s+\d\d+\s+\d\d:\d\d:\d\d 177 | # 16 Jun 94 07:29:35 178 | (?:\s+\w\w\w|\s[+-]\d\d\d\d)? 179 | # (optional timezone) 180 | | 181 | \w\w\w\s+\w\w\w\s+\d\d\s+\d\d:\d\d 182 | # lastlog format 183 | )\b 184 | }{ 185 | $use_format 186 | ? strftime($format, localtime(str2time($1))) 187 | : concise(ago(time - str2time($1), 2)) 188 | }exg; 189 | 190 | print $_; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /vidir: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | vidir - edit directories and filenames 6 | 7 | =head1 SYNOPSIS 8 | 9 | B [B<--verbose>] [I|I|B<->]... 10 | 11 | =head1 DESCRIPTION 12 | 13 | B allows editing of directories and filenames in a text editor. If no 14 | I is specified, the filenames of the current directory are edited. 15 | 16 | When editing a directory, each item in the directory will appear on its own 17 | numbered line. These numbers are how vidir keeps track of what items are 18 | changed. Delete lines to remove files from the directory, or 19 | edit filenames to rename files. You can also switch pairs of numbers to 20 | swap filenames. 21 | 22 | Filenames to be edited may be given any combination of Is (which 23 | will be expanded to the non-recursive list of all files within I), 24 | Is, or I<->. If the latter is specified, B reads a list of 25 | filenames from stdin and displays those for editing. 26 | 27 | =head1 OPTIONS 28 | 29 | =over 4 30 | 31 | =item -v, --verbose 32 | 33 | Verbosely display the actions taken by the program. 34 | 35 | =back 36 | 37 | =head1 EXAMPLES 38 | 39 | =over 4 40 | 41 | =item vidir 42 | 43 | =item vidir *.jpeg 44 | 45 | Typical uses. 46 | 47 | =item find | vidir - 48 | 49 | Edit subdirectory contents too. To delete subdirectories, 50 | delete all their contents and the subdirectory itself in the editor. 51 | 52 | =item find -type f | vidir - 53 | 54 | Edit all files under the current directory and subdirectories. 55 | 56 | =back 57 | 58 | =head1 ENVIRONMENT VARIABLES 59 | 60 | =over 4 61 | 62 | =item EDITOR 63 | 64 | Editor to use. 65 | 66 | =item VISUAL 67 | 68 | Also supported to determine what editor to use. 69 | 70 | =back 71 | 72 | =head1 AUTHOR 73 | 74 | Copyright 2006 by Joey Hess 75 | 76 | Licensed under the GNU GPL. 77 | 78 | =cut 79 | 80 | use File::Basename; 81 | use File::Path qw(make_path); 82 | use File::Spec; 83 | use File::Temp; 84 | use Getopt::Long; 85 | 86 | my $error=0; 87 | 88 | my $verbose=0; 89 | if (! GetOptions("verbose|v" => \$verbose)) { 90 | die "Usage: $0 [--verbose] [directory|file|-]\n"; 91 | } 92 | 93 | my @dir; 94 | if (! @ARGV) { 95 | push @ARGV, "." 96 | } 97 | foreach my $item (@ARGV) { 98 | if ($item eq "-") { 99 | push @dir, map { chomp; $_ } ; 100 | close STDIN; 101 | open(STDIN, "/dev/tty") || die "reopen: $!\n"; 102 | } 103 | elsif (-d $item) { 104 | $item =~ s{/?$}{/}; 105 | opendir(DIR, $item) || die "$0: cannot read $item: $!\n"; 106 | push @dir, map { "$item$_" } sort readdir(DIR); 107 | closedir DIR; 108 | } 109 | else { 110 | push @dir, $item; 111 | } 112 | } 113 | 114 | if (grep(/[[:cntrl:]]/, @dir)) { 115 | die "$0: control characters in filenames are not supported\n"; 116 | } 117 | 118 | my $tmp=File::Temp->new(TEMPLATE => "dirXXXXX", DIR => File::Spec->tmpdir); 119 | open (OUT, ">".$tmp->filename) || die "$0: cannot create ".$tmp->filename.": $!\n"; 120 | 121 | my %item; 122 | my $c=0; 123 | my $l = $#dir =~ tr/0-9//; 124 | foreach (@dir) { 125 | next if /^(.*\/)?\.$/ || /^(.*\/)?\.\.$/; 126 | $item{++$c}=$_; 127 | printf OUT "%0*d\t%s\n", $l, $c, $_; 128 | } 129 | @dir=(); 130 | close OUT || die "$0: cannot write ".$tmp->filename.": $!\n"; 131 | 132 | my @editor="vi"; 133 | if (-x "/usr/bin/editor") { 134 | @editor="/usr/bin/editor"; 135 | } 136 | if (exists $ENV{EDITOR}) { 137 | @editor=split(' ', $ENV{EDITOR}); 138 | } 139 | if (exists $ENV{VISUAL}) { 140 | @editor=split(' ', $ENV{VISUAL}); 141 | } 142 | $ret=system(@editor, $tmp); 143 | if ($ret != 0) { 144 | die "@editor exited nonzero, aborting\n"; 145 | } 146 | 147 | open (IN, $tmp->filename) || die "$0: cannot read ".$tmp->filename.": $!\n"; 148 | while () { 149 | chomp; 150 | if (/^(\d+)\t{0,1}(.*)/) { 151 | my $num=int($1); 152 | my $name=$2; 153 | if (! exists $item{$num}) { 154 | die "$0: unknown item number $num\n"; 155 | } 156 | elsif ($name ne $item{$num}) { 157 | next unless length $name; 158 | my $src=$item{$num}; 159 | my $dir=dirname($name); 160 | 161 | if (! (-e $src || -l $src) ) { 162 | print STDERR "$0: $src does not exist\n"; 163 | delete $item{$num}; 164 | next; 165 | } 166 | 167 | # deal with swaps 168 | if (-e $name || -l $name) { 169 | my $tmp=$name."~"; 170 | my $c=0; 171 | while (-e $tmp || -l $tmp) { 172 | $c++; 173 | $tmp=$name."~$c"; 174 | } 175 | if (! rename($name, $tmp)) { 176 | print STDERR "$0: failed to rename $name to $tmp: $!\n"; 177 | $error=1; 178 | } 179 | elsif ($verbose) { 180 | print "'$name' -> '$tmp'\n"; 181 | } 182 | foreach my $item (keys %item) { 183 | if ($item{$item} eq $name) { 184 | $item{$item}=$tmp; 185 | } 186 | } 187 | } 188 | 189 | if ((! -d $dir) && (! make_path($dir, { 190 | verbose => $verbose, 191 | }))) { 192 | print STDERR "$0: failed to create directory tree $dir: $!\n"; 193 | $error=1; 194 | } 195 | elsif (! rename($src, $name)) { 196 | print STDERR "$0: failed to rename $src to $name: $!\n"; 197 | $error=1; 198 | } 199 | else { 200 | if (-d $name) { 201 | foreach (values %item) { 202 | s,^\Q$src\E($|/),$name$1,; 203 | } 204 | } 205 | if ($verbose) { 206 | print "'$src' => '$name'\n"; 207 | } 208 | } 209 | } 210 | delete $item{$num}; 211 | } 212 | elsif (/^\s*$/) { 213 | # skip empty line 214 | } 215 | else { 216 | die "$0: unable to parse line \"$_\", aborting\n"; 217 | } 218 | } 219 | close IN || die "$0: cannot read ".$tmp->filename.": $!\n"; 220 | unlink($tmp.'~') if -e $tmp.'~'; 221 | 222 | sub rm { 223 | my $file = shift; 224 | 225 | if (-d $file && ! -l $file) { 226 | return rmdir $file; 227 | } 228 | else { 229 | return unlink $file; 230 | } 231 | } 232 | 233 | foreach my $item (reverse sort values %item) { 234 | if (! rm($item)) { 235 | print STDERR "$0: failed to remove $item: $!\n"; 236 | $error=1; 237 | } 238 | if ($verbose) { 239 | print "removed '$item'\n"; 240 | } 241 | } 242 | 243 | exit $error; 244 | -------------------------------------------------------------------------------- /errno.c: -------------------------------------------------------------------------------- 1 | /* 2 | * errno.c -- look up errno names and descriptions 3 | * Copyright 2012 Lars Wirzenius (liw@iki.fi) 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 13 | * Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | static struct { 34 | const char *name; 35 | int code; 36 | } errnos[] = { 37 | #include "errnos.h" 38 | }; 39 | static const int num_errnos = sizeof(errnos) / sizeof(errnos[0]); 40 | 41 | 42 | static void 43 | report(const char *name, int code) 44 | { 45 | printf("%s %d %s\n", name, code, strerror(code)); 46 | } 47 | 48 | 49 | static bool 50 | report_from_name(const char *name) 51 | { 52 | int i; 53 | for (i = 0; i < num_errnos; ++i) { 54 | if (strcasecmp(errnos[i].name, name) == 0) { 55 | report(errnos[i].name, errnos[i].code); 56 | return true; 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | 63 | static bool 64 | report_from_code(int code) 65 | { 66 | int i; 67 | for (i = 0; i < num_errnos; ++i) { 68 | if (errnos[i].code == code) { 69 | report(errnos[i].name, code); 70 | return true; 71 | } 72 | } 73 | return false; 74 | } 75 | 76 | 77 | static bool 78 | matches(int code, int num_words, char **words) 79 | { 80 | const char *text = strerror(code); 81 | int i; 82 | 83 | for (i = 0; i < num_words; ++i) { 84 | if (strcasestr(text, words[i]) == NULL) 85 | return false; 86 | } 87 | return true; 88 | } 89 | 90 | 91 | static void 92 | search(int num_words, char **words) 93 | { 94 | int i; 95 | 96 | for (i = 0; i < num_errnos; ++i) { 97 | if (matches(errnos[i].code, num_words, words)) 98 | report(errnos[i].name, errnos[i].code); 99 | } 100 | } 101 | 102 | 103 | static void 104 | search_all(int num_words, char **words) 105 | { 106 | FILE *f; 107 | 108 | /* Static buffers are ugly, but they're simple. If anyone has a 109 | locale name longer than a kilobyte, they will suffer, and they 110 | will complain, and then I will fix this. */ 111 | char line[1024]; 112 | 113 | f = popen("locale -a", "r"); 114 | if (f == NULL) { 115 | fprintf(stderr, "ERROR: Can't execute locale -a: %d: %s\n", 116 | errno, strerror(errno)); 117 | exit(EXIT_FAILURE); 118 | } 119 | 120 | while (fgets(line, sizeof line, f) != NULL) { 121 | line[strcspn(line, "\n")] = '\0'; 122 | setlocale(LC_ALL, line); 123 | search(num_words, words); 124 | } 125 | 126 | pclose(f); 127 | } 128 | 129 | 130 | static struct option 131 | options[] = { 132 | { "help", 0, NULL, 'h' }, 133 | { "list", 0, NULL, 'l' }, 134 | { "search", 0, NULL, 's' }, 135 | { "search-all-locales", 0, NULL, 'S' }, 136 | { 0, 0, 0, 0 } 137 | }; 138 | 139 | 140 | static void 141 | usage(void) 142 | { 143 | printf("Usage: errno [-lsS] [--list] [--search] [--search-all-locales] " 144 | "[keyword]\n"); 145 | } 146 | 147 | 148 | int 149 | main(int argc, char **argv) 150 | { 151 | int i; 152 | int exit_code; 153 | int index = 0; 154 | enum { 155 | lookup_mode, 156 | list_mode, 157 | search_mode, 158 | search_all_mode 159 | } mode = lookup_mode; 160 | 161 | setlocale(LC_ALL, ""); 162 | 163 | for (;;) { 164 | int c = getopt_long(argc, argv, "hlsS", options, &index); 165 | if (c == -1) 166 | break; 167 | 168 | switch (c) { 169 | case 'h': 170 | usage(); 171 | return EXIT_SUCCESS; 172 | 173 | case 'l': 174 | mode = list_mode; 175 | break; 176 | 177 | case 's': 178 | mode = search_mode; 179 | break; 180 | 181 | case 'S': 182 | mode = search_all_mode; 183 | break; 184 | 185 | case '?': 186 | break; 187 | 188 | default: 189 | fprintf(stderr, "getopt returned 0x%02x\n", c); 190 | return EXIT_FAILURE; 191 | } 192 | } 193 | 194 | exit_code = EXIT_SUCCESS; 195 | 196 | switch (mode) { 197 | case lookup_mode: 198 | for (i = optind; i < argc; ++i) { 199 | const char *arg = argv[i]; 200 | if (toupper(arg[0]) == 'E') { 201 | if (!report_from_name(arg)) 202 | exit_code = EXIT_FAILURE; 203 | } else if (isdigit(arg[0])) { 204 | if (!report_from_code(atoi(arg))) 205 | exit_code = EXIT_FAILURE; 206 | } else { 207 | fprintf(stderr, "ERROR: Not understood: %s\n", arg); 208 | exit_code = EXIT_FAILURE; 209 | } 210 | } 211 | break; 212 | 213 | case list_mode: 214 | for (i = 0; i < num_errnos; ++i) 215 | report(errnos[i].name, errnos[i].code); 216 | break; 217 | 218 | case search_mode: 219 | search(argc - optind, argv + optind); 220 | break; 221 | 222 | case search_all_mode: 223 | search_all(argc - optind, argv + optind); 224 | break; 225 | } 226 | 227 | return exit_code; 228 | } 229 | -------------------------------------------------------------------------------- /lckdo.c: -------------------------------------------------------------------------------- 1 | /* lckdo.c: run a program with a lock held, 2 | * to prevent multiple processes running in parallel. 3 | * Use just like `nice' or `nohup'. 4 | * Written by Michael Tokarev 5 | * Public domain. 6 | */ 7 | 8 | #define _GNU_SOURCE 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* compile with -DUSE_FLOCK to use flock() instead of fcntl() */ 22 | 23 | #if !defined(USE_FLOCK) && !defined(F_SETLKW) 24 | # define USE_FLOCK 25 | #endif 26 | 27 | #ifndef __GNUC__ 28 | # ifndef __attribute__ 29 | # define __attribute__(x) 30 | # endif 31 | #endif 32 | 33 | static char *progname; 34 | static void 35 | __attribute__((format(printf,3,4))) 36 | __attribute__((noreturn)) 37 | error(int errnum, int exitcode, const char *fmt, ...) { 38 | va_list ap; 39 | fprintf(stderr, "%s: ", progname); 40 | va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); 41 | if (errnum) 42 | fprintf(stderr, ": %s\n", strerror(errnum)); 43 | else 44 | fputs("\n", stderr); 45 | exit(exitcode); 46 | } 47 | 48 | static const char *lckfile; 49 | static int quiet; 50 | 51 | static void sigalarm(int sig) { 52 | if (quiet) 53 | _exit(EX_TEMPFAIL); 54 | error(0, EX_TEMPFAIL, 55 | "lock file `%s' is already locked (timeout waiting)", lckfile); 56 | } 57 | 58 | int main(int argc, char **argv) { 59 | int fd; 60 | int c; 61 | int create = O_CREAT; 62 | int dofork = 1; 63 | int waittime = 0; 64 | int shared = 0; 65 | int test = 0; 66 | int fdn = -1; 67 | #ifndef USE_FLOCK 68 | struct flock fl; 69 | #endif 70 | 71 | if ((progname = strrchr(argv[0], '/')) == NULL) 72 | progname = argv[0]; 73 | else 74 | argv[0] = ++progname; 75 | 76 | if (argc == 1) { 77 | printf( 78 | "%s: execute a program with a lock set.\n" 79 | "Usage: %s [options] lockfile program [arguments]\n" 80 | "where options are:\n" 81 | " -w - if the lock is already held by another process,\n" 82 | " wait for it to complete instead of failing immediately\n" 83 | " -W sec - the same as -w but wait not more than sec seconds\n" 84 | " -e - execute the program directly, no fork/wait\n" 85 | " (keeps extra open file descriptor)\n" 86 | " -E nnn - set the fd# to keep open in -e case (implies -e)\n" 87 | " -n - do not create the lock file if it does not exist\n" 88 | " -q - produce no output if lock is already held\n" 89 | " -s - lock in shared (read) mode\n" 90 | " -x - lock in exclusive (write) mode (default)\n" 91 | " -t - test for lock existence" 92 | #ifndef USE_FLOCK 93 | " (just prints pid if any with -q)\n" 94 | #endif 95 | " (implies -n)\n" 96 | , progname, progname); 97 | return 0; 98 | } 99 | 100 | while ((c = getopt(argc, argv, "+wW:neE:sxtq")) != EOF) { 101 | switch(c) { 102 | case 'w': 103 | if (!waittime) 104 | waittime = -1; 105 | break; 106 | case 'W': 107 | if ((waittime = atoi(optarg)) < 1) 108 | error(0, EX_USAGE, "invalid wait time `%s'", optarg); 109 | break; 110 | case 't': 111 | test = 1; 112 | /* fall thru */ 113 | case 'n': 114 | create = 0; 115 | break; 116 | case 'E': 117 | if ((fdn = atoi(optarg)) < 0 || fdn == 2) 118 | error(0, EX_USAGE, "invalid fd# `%s'", optarg); 119 | /* fall thru */ 120 | case 'e': 121 | dofork = 0; 122 | break; 123 | case 's': 124 | shared = 1; 125 | break; 126 | case 'x': 127 | shared = 0; 128 | break; 129 | case 'q': 130 | quiet = 1; 131 | break; 132 | default: 133 | return EX_USAGE; 134 | } 135 | } 136 | 137 | argc -= optind; argv += optind; 138 | if (!argc || (!test && argc < 2)) 139 | error(0, EX_USAGE, "too few arguments given"); 140 | 141 | lckfile = *argv++; 142 | 143 | #ifdef USE_FLOCK 144 | create |= O_RDONLY; 145 | #else 146 | if (!test) 147 | create |= shared ? O_RDONLY : O_WRONLY; 148 | #endif 149 | fd = open(lckfile, create, 0666); 150 | if (fd < 0) { 151 | if (test && errno == ENOENT) { 152 | if (!quiet) 153 | printf("lockfile `%s' is not locked\n", lckfile); 154 | return 0; 155 | } 156 | error(errno, EX_CANTCREAT, "unable to open `%s'", lckfile); 157 | } 158 | 159 | if (!test && fdn >= 0) { 160 | /* dup it early to comply with stupid POSIX fcntl locking 161 | * semantics */ 162 | if (dup2(fd, fdn) < 0) 163 | error(errno, EX_OSERR, "dup2(%d,%d) failed", fd, fdn); 164 | close(fd); 165 | fd = fdn; 166 | } 167 | 168 | if (test) 169 | waittime = 0; 170 | else if (waittime > 0) { 171 | alarm(waittime); 172 | signal(SIGALRM, sigalarm); 173 | } 174 | #ifdef USE_FLOCK 175 | c = flock(fd, (shared ? LOCK_SH : LOCK_EX) | (waittime ? 0 : LOCK_NB)); 176 | if (test && c < 0 && 177 | (errno == EWOULDBLOCK || errno == EAGAIN || errno == EACCES)) { 178 | if (!quiet) 179 | printf("lockfile `%s' is locked\n", lckfile); 180 | else 181 | printf("locked\n"); 182 | return EX_TEMPFAIL; 183 | } 184 | #else 185 | memset(&fl, 0, sizeof(fl)); 186 | fl.l_type = shared ? F_RDLCK : F_WRLCK; 187 | c = fcntl(fd, test ? F_GETLK : waittime ? F_SETLKW : F_SETLK, &fl); 188 | if (test && c == 0) { 189 | if (fl.l_type == F_UNLCK) { 190 | if (!quiet) 191 | printf("lockfile `%s' is not locked\n", lckfile); 192 | return 0; 193 | } 194 | if (!quiet) 195 | printf("lockfile `%s' is locked by process %d\n", lckfile, fl.l_pid); 196 | else 197 | printf("%d\n", fl.l_pid); 198 | return EX_TEMPFAIL; 199 | } 200 | #endif 201 | if (waittime > 0) 202 | alarm(0); 203 | if (c < 0) { 204 | if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EACCES) 205 | error(errno, EX_OSERR, "unable to lock `%s'", lckfile); 206 | else if (quiet) 207 | return EX_TEMPFAIL; 208 | else 209 | error(0, EX_TEMPFAIL, "lockfile `%s' is already locked", lckfile); 210 | } 211 | 212 | if (dofork) { 213 | pid_t pid; 214 | int flags = fcntl(fd, F_GETFD, 0); 215 | if (flags < 0) 216 | error(errno, EX_OSERR, "fcntl() failed"); 217 | fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 218 | pid = fork(); 219 | if (pid < 0) 220 | error(errno, EX_OSERR, "unable to fork"); 221 | else if (pid) { 222 | if (wait(&c) < 0) 223 | error(errno, EX_OSERR, "wait() failed"); 224 | if (WIFSIGNALED(c)) 225 | error(0, EX_SOFTWARE, "%s: %s", *argv, 226 | strsignal(WTERMSIG(c))); 227 | return WEXITSTATUS(c); 228 | } 229 | } 230 | execvp(*argv, argv); 231 | error(errno, EX_OSERR, "unable to execute %s", *argv); 232 | } 233 | -------------------------------------------------------------------------------- /mispipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mispipe: written by Nathanael Nerode. 3 | * 4 | * Copyright 2004 Nathanael Nerode. 5 | * 6 | * Licensed under the GPL version 2 or above, and dual-licensed under the 7 | * following license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a 10 | * copy of this software and associated documentation files (the "Software"), 11 | * to deal in the Software without restriction, including without limitation 12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | * and/or sell copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | /* 29 | * Usage: mispipe 30 | * Run | , but return with the exit status of . 31 | * 32 | * This is designed for a very specific purpose: logging. 33 | * "foo | logger -t foo" 34 | * will return with the exit status of logger, not that of foo. 35 | * "mispipe foo 'logger -t foo'" 36 | * will return with the exit status of foo. 37 | */ 38 | 39 | /* 40 | * To do: 41 | * Make this into a fancy, internationalized, option-handling hellbeast. 42 | * (But why bother? It does its job quite well.) 43 | */ 44 | 45 | #include /* errno */ 46 | #include 47 | #include /* pipe(), fork(),... */ 48 | #include /* system() */ 49 | #include /* waitpid(), etc. */ 50 | #include 51 | #include /* va_list, for error() */ 52 | 53 | static const char* progname; /* Stores argv[0] */ 54 | static int filedes[2]; /* Stores pipe file descriptors */ 55 | 56 | /* Subroutine for 'warning' and 'error' which prefixes progname */ 57 | static void warning_prefix(void) { 58 | fputs(progname, stderr); 59 | fputs(": ", stderr); 60 | } 61 | 62 | /* Issue a warning, then die */ 63 | __attribute__(( noreturn, format (printf, 1, 2) )) 64 | static void error(const char* formatstr, ...) { 65 | va_list ap; 66 | va_start(ap, formatstr); 67 | warning_prefix(); 68 | vfprintf(stderr, formatstr, ap); 69 | va_end(ap); 70 | exit(1); 71 | } 72 | 73 | /* Issue a warning, then die, with errno */ 74 | __attribute__(( noreturn )) 75 | static void error_with_errno(const char* message) { 76 | int saved_errno; 77 | saved_errno=errno; 78 | warning_prefix(); 79 | fputs(message, stderr); 80 | fputs(": error number ", stderr); 81 | fprintf(stderr, "%i\n", saved_errno); 82 | exit(1); 83 | } 84 | 85 | /* Convert 'wait'/'system'-style exit status to 'exit'-style exit status */ 86 | __attribute__(( const )) 87 | static int shorten_status(int status_big) { 88 | if (WIFEXITED(status_big)) 89 | return WEXITSTATUS(status_big); 90 | if (WIFSIGNALED(status_big)) 91 | return 128+WTERMSIG(status_big); 92 | if (WIFSTOPPED(status_big)) 93 | return 128+WSTOPSIG(status_big); 94 | #ifdef WCOREDUMP 95 | if (WCOREDUMP(status_big)) 96 | error("Ow, somebody dumped core!"); 97 | #endif 98 | error("shorten_status got an invalid status (?!)"); 99 | } 100 | 101 | /* All the work for command 2. */ 102 | __attribute__(( noreturn )) 103 | static void subprocess2(const char* cmd) { 104 | /* Close the old standard input. */ 105 | if (close(0)) 106 | error_with_errno("Failed (in child) closing standard input"); 107 | /* Make the reading end of the pipe the new standard input. */ 108 | if (dup2(filedes[0], 0) == -1) 109 | error_with_errno("Failed (in child) redefining standard input"); 110 | /* Close the original file descriptor for it */ 111 | if (close(filedes[0])) 112 | error_with_errno("Failed (in child) closing filedes[0]"); 113 | /* Close the other end of the pipe. */ 114 | if (close(filedes[1])) 115 | error_with_errno("Failed (in child) closing filedes[1]"); 116 | /* Do the second command, and throw away the exit status. */ 117 | if (system(cmd)) {} 118 | /* Close the standard input. */ 119 | if (close(0)) 120 | error_with_errno("Failed (in child) closing standard output " 121 | " (while cleaning up)"); 122 | exit(0); 123 | } 124 | 125 | int main (int argc, const char ** argv) { 126 | int status_big; /* Exit status, 'wait' and 'system' style */ 127 | pid_t child2_pid; 128 | pid_t dead_pid; 129 | 130 | /* Set progname */ 131 | progname = argv[0]; 132 | 133 | /* Verify arguments */ 134 | if (argc != 3) 135 | error("Wrong number of args, aborting\n"); 136 | /* Open a new pipe */ 137 | if (pipe(filedes)) 138 | error_with_errno("pipe() failed"); 139 | 140 | /* Fork to run second command */ 141 | child2_pid = fork(); 142 | if (child2_pid == 0) 143 | subprocess2(argv[2]); 144 | if (child2_pid == -1) 145 | error_with_errno("fork() failed"); 146 | 147 | /* Run first command inline (seriously!) */ 148 | /* Close standard output. */ 149 | if (close(1)) 150 | error_with_errno("Failed closing standard output"); 151 | /* Make the writing end of the pipe the new standard output. */ 152 | if (dup2(filedes[1], 1) == -1) 153 | error_with_errno("Failed redefining standard output"); 154 | /* Close the original file descriptor for it. */ 155 | if (close(filedes[1])) 156 | error_with_errno("Failed closing filedes[1]"); 157 | /* Close the other end of the pipe. */ 158 | if (close(filedes[0])) 159 | error_with_errno("Failed closing filedes[0]"); 160 | /* Do the first command, and (crucially) get the status. */ 161 | status_big = system(argv[1]); 162 | 163 | /* Close standard output. */ 164 | if (close(1)) 165 | error_with_errno("Failed closing standard output (while cleaning up)"); 166 | 167 | /* Wait for the other process to exit. */ 168 | /* We don't care about the status. */ 169 | dead_pid = waitpid(child2_pid, NULL, WUNTRACED); 170 | if (dead_pid == -1) { 171 | error_with_errno("waitpid() failed"); 172 | } 173 | else if (dead_pid != child2_pid) { 174 | error("waitpid(): Who died? %i\n", dead_pid); 175 | } 176 | 177 | /* Return the desired exit status. */ 178 | return shorten_status(status_big); 179 | } 180 | -------------------------------------------------------------------------------- /physmem.c: -------------------------------------------------------------------------------- 1 | /* Calculate the size of physical memory. 2 | 3 | Copyright (C) 2000, 2001, 2003, 2005, 2006 Free Software 4 | Foundation, Inc. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2, or (at your option) 9 | any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software Foundation, 18 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19 | 20 | /* Written by Paul Eggert. */ 21 | 22 | #include 23 | 24 | #if HAVE_SYS_PSTAT_H 25 | # include 26 | #endif 27 | 28 | #if HAVE_SYS_SYSMP_H 29 | # include 30 | #endif 31 | 32 | #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H 33 | # include 34 | # include 35 | #endif 36 | 37 | #if HAVE_SYS_TABLE_H 38 | # include 39 | #endif 40 | 41 | #include 42 | 43 | #if HAVE_SYS_PARAM_H 44 | # include 45 | #endif 46 | 47 | #if HAVE_SYS_SYSCTL_H 48 | # include 49 | #endif 50 | 51 | #if HAVE_SYS_SYSTEMCFG_H 52 | # include 53 | #endif 54 | 55 | #ifdef _WIN32 56 | # define WIN32_LEAN_AND_MEAN 57 | # include 58 | /* MEMORYSTATUSEX is missing from older windows headers, so define 59 | a local replacement. */ 60 | typedef struct 61 | { 62 | DWORD dwLength; 63 | DWORD dwMemoryLoad; 64 | DWORDLONG ullTotalPhys; 65 | DWORDLONG ullAvailPhys; 66 | DWORDLONG ullTotalPageFile; 67 | DWORDLONG ullAvailPageFile; 68 | DWORDLONG ullTotalVirtual; 69 | DWORDLONG ullAvailVirtual; 70 | DWORDLONG ullAvailExtendedVirtual; 71 | } lMEMORYSTATUSEX; 72 | typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); 73 | #endif 74 | 75 | #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) 76 | 77 | /* Return the total amount of physical memory. */ 78 | double 79 | physmem_total (void) 80 | { 81 | #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE 82 | { /* This works on linux-gnu, solaris2 and cygwin. */ 83 | double pages = sysconf (_SC_PHYS_PAGES); 84 | double pagesize = sysconf (_SC_PAGESIZE); 85 | if (0 <= pages && 0 <= pagesize) 86 | return pages * pagesize; 87 | } 88 | #endif 89 | 90 | #if HAVE_PSTAT_GETSTATIC 91 | { /* This works on hpux11. */ 92 | struct pst_static pss; 93 | if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)) 94 | { 95 | double pages = pss.physical_memory; 96 | double pagesize = pss.page_size; 97 | if (0 <= pages && 0 <= pagesize) 98 | return pages * pagesize; 99 | } 100 | } 101 | #endif 102 | 103 | #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 104 | { /* This works on irix6. */ 105 | struct rminfo realmem; 106 | if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 107 | { 108 | double pagesize = sysconf (_SC_PAGESIZE); 109 | double pages = realmem.physmem; 110 | if (0 <= pages && 0 <= pagesize) 111 | return pages * pagesize; 112 | } 113 | } 114 | #endif 115 | 116 | #if HAVE_GETSYSINFO && defined GSI_PHYSMEM 117 | { /* This works on Tru64 UNIX V4/5. */ 118 | int physmem; 119 | 120 | if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem), 121 | NULL, NULL, NULL) == 1) 122 | { 123 | double kbytes = physmem; 124 | 125 | if (0 <= kbytes) 126 | return kbytes * 1024.0; 127 | } 128 | } 129 | #endif 130 | 131 | #if HAVE_SYSCTL && defined HW_PHYSMEM 132 | { /* This works on *bsd and darwin. */ 133 | unsigned int physmem; 134 | size_t len = sizeof physmem; 135 | static int mib[2] = { CTL_HW, HW_PHYSMEM }; 136 | 137 | if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0 138 | && len == sizeof (physmem)) 139 | return (double) physmem; 140 | } 141 | #endif 142 | 143 | #if HAVE__SYSTEM_CONFIGURATION 144 | /* This works on AIX. */ 145 | return _system_configuration.physmem; 146 | #endif 147 | 148 | #if defined _WIN32 149 | { /* this works on windows */ 150 | PFN_MS_EX pfnex; 151 | HMODULE h = GetModuleHandle ("kernel32.dll"); 152 | 153 | if (!h) 154 | return 0.0; 155 | 156 | /* Use GlobalMemoryStatusEx if available. */ 157 | if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 158 | { 159 | lMEMORYSTATUSEX lms_ex; 160 | lms_ex.dwLength = sizeof lms_ex; 161 | if (!pfnex (&lms_ex)) 162 | return 0.0; 163 | return (double) lms_ex.ullTotalPhys; 164 | } 165 | 166 | /* Fall back to GlobalMemoryStatus which is always available. 167 | but returns wrong results for physical memory > 4GB. */ 168 | else 169 | { 170 | MEMORYSTATUS ms; 171 | GlobalMemoryStatus (&ms); 172 | return (double) ms.dwTotalPhys; 173 | } 174 | } 175 | #endif 176 | 177 | /* Guess 64 MB. It's probably an older host, so guess small. */ 178 | return 64 * 1024 * 1024; 179 | } 180 | 181 | /* Return the amount of physical memory available. */ 182 | double 183 | physmem_available (void) 184 | { 185 | #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE 186 | { /* This works on linux-gnu, solaris2 and cygwin. */ 187 | double pages = sysconf (_SC_AVPHYS_PAGES); 188 | double pagesize = sysconf (_SC_PAGESIZE); 189 | if (0 <= pages && 0 <= pagesize) 190 | return pages * pagesize; 191 | } 192 | #endif 193 | 194 | #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC 195 | { /* This works on hpux11. */ 196 | struct pst_static pss; 197 | struct pst_dynamic psd; 198 | if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0) 199 | && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0)) 200 | { 201 | double pages = psd.psd_free; 202 | double pagesize = pss.page_size; 203 | if (0 <= pages && 0 <= pagesize) 204 | return pages * pagesize; 205 | } 206 | } 207 | #endif 208 | 209 | #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 210 | { /* This works on irix6. */ 211 | struct rminfo realmem; 212 | if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 213 | { 214 | double pagesize = sysconf (_SC_PAGESIZE); 215 | double pages = realmem.availrmem; 216 | if (0 <= pages && 0 <= pagesize) 217 | return pages * pagesize; 218 | } 219 | } 220 | #endif 221 | 222 | #if HAVE_TABLE && defined TBL_VMSTATS 223 | { /* This works on Tru64 UNIX V4/5. */ 224 | struct tbl_vmstats vmstats; 225 | 226 | if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1) 227 | { 228 | double pages = vmstats.free_count; 229 | double pagesize = vmstats.pagesize; 230 | 231 | if (0 <= pages && 0 <= pagesize) 232 | return pages * pagesize; 233 | } 234 | } 235 | #endif 236 | 237 | #if HAVE_SYSCTL && defined HW_USERMEM 238 | { /* This works on *bsd and darwin. */ 239 | unsigned int usermem; 240 | size_t len = sizeof usermem; 241 | static int mib[2] = { CTL_HW, HW_USERMEM }; 242 | 243 | if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0 244 | && len == sizeof (usermem)) 245 | return (double) usermem; 246 | } 247 | #endif 248 | 249 | #if defined _WIN32 250 | { /* this works on windows */ 251 | PFN_MS_EX pfnex; 252 | HMODULE h = GetModuleHandle ("kernel32.dll"); 253 | 254 | if (!h) 255 | return 0.0; 256 | 257 | /* Use GlobalMemoryStatusEx if available. */ 258 | if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 259 | { 260 | lMEMORYSTATUSEX lms_ex; 261 | lms_ex.dwLength = sizeof lms_ex; 262 | if (!pfnex (&lms_ex)) 263 | return 0.0; 264 | return (double) lms_ex.ullAvailPhys; 265 | } 266 | 267 | /* Fall back to GlobalMemoryStatus which is always available. 268 | but returns wrong results for physical memory > 4GB */ 269 | else 270 | { 271 | MEMORYSTATUS ms; 272 | GlobalMemoryStatus (&ms); 273 | return (double) ms.dwAvailPhys; 274 | } 275 | } 276 | #endif 277 | 278 | /* Guess 25% of physical memory. */ 279 | return physmem_total () / 4; 280 | } 281 | 282 | 283 | #if DEBUG 284 | 285 | # include 286 | # include 287 | 288 | int 289 | main (void) 290 | { 291 | printf ("%12.f %12.f\n", physmem_total (), physmem_available ()); 292 | exit (0); 293 | } 294 | 295 | #endif /* DEBUG */ 296 | 297 | /* 298 | Local Variables: 299 | compile-command: "gcc -DDEBUG -g -O -Wall -W physmem.c" 300 | End: 301 | */ 302 | -------------------------------------------------------------------------------- /ifdata.docbook: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | Joey 32 | Hess 33 | 34 | 2006-03-07 35 | 36 | 37 | 38 | ifdata 39 | 1 40 | moreutils 41 | moreutils 42 | 43 | 44 | 45 | ifdata 46 | get network interface info without 47 | parsing ifconfig output 48 | 49 | 50 | 51 | 52 | ifdata 53 | options 54 | iface 55 | 56 | 57 | 58 | 59 | DESCRIPTION 60 | 61 | 62 | ifdata can be used to check for 63 | the existence of a network interface, or to get 64 | information about the interface, such as its IP 65 | address. Unlike ifconfig or 66 | ip, ifdata 67 | has simple to parse output that is designed to be 68 | easily used by a shell script. 69 | 70 | 71 | 72 | 73 | 74 | OPTIONS 75 | 76 | 77 | 78 | 79 | 80 | 81 | Print out a help summary. 82 | 83 | 84 | 85 | 86 | 87 | 88 | Test to see if the interface exists, 89 | exit nonzero if it does not. 90 | 91 | 92 | 93 | 94 | 95 | 96 | Prints out the whole configuration of 97 | the interface. 98 | 99 | 100 | 101 | 102 | 103 | 104 | Prints "yes" or "no" if the interface 105 | exists or not. 106 | 107 | 108 | 109 | 110 | 111 | 112 | Prints the IPv4 address of the 113 | interface. 114 | 115 | 116 | 117 | 118 | 119 | 120 | Prints the netmask of the 121 | interface. 122 | 123 | 124 | 125 | 126 | 127 | 128 | Prints the network address of the 129 | interface. 130 | 131 | 132 | 133 | 134 | 135 | 136 | Prints the broadcast address of the 137 | interface. 138 | 139 | 140 | 141 | 142 | 143 | 144 | Prints the MTU of the interface. 145 | 146 | 147 | 148 | 149 | 150 | Following options are Linux only. 151 | 152 | 153 | 154 | 155 | 156 | 157 | Prints the hardware address of the 158 | interface. Exit with a failure exit code 159 | if there is not hardware address for the 160 | given network interface. 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | Prints the flags of the 169 | interface. 170 | 171 | 172 | 173 | 174 | 175 | 176 | Prints out all the input statistics 177 | of the interface. 178 | 179 | 180 | 181 | 182 | 183 | 184 | Prints the number of input packets. 185 | 186 | 187 | 188 | 189 | 190 | 191 | Prints the number of input bytes. 192 | 193 | 194 | 195 | 196 | 197 | 198 | Prints the number of input errors. 199 | 200 | 201 | 202 | 203 | 204 | 205 | Prints the number of dropped input 206 | packets. 207 | 208 | 209 | 210 | 211 | 212 | 213 | Prints the number of input fifo overruns. 214 | 215 | 216 | 217 | 218 | 219 | 220 | Print the number of compressed input 221 | packets. 222 | 223 | 224 | 225 | 226 | 227 | 228 | Prints the number of input 229 | multicast packets. 230 | 231 | 232 | 233 | 234 | 235 | 236 | Prints out all the output statistics 237 | of the interface. 238 | 239 | 240 | 241 | 242 | 243 | 244 | Prints the number of output packets. 245 | 246 | 247 | 248 | 249 | 250 | 251 | Prints the number of output bytes. 252 | 253 | 254 | 255 | 256 | 257 | 258 | Prints the number of output errors. 259 | 260 | 261 | 262 | 263 | 264 | 265 | Prints the number of dropped 266 | output packets. 267 | 268 | 269 | 270 | 271 | 272 | 273 | Prints the number of output fifo overruns. 274 | 275 | 276 | 277 | 278 | 279 | 280 | Print the number of output collisions. 281 | 282 | 283 | 284 | 285 | 286 | 287 | Prints the number of output carrier 288 | losses. 289 | 290 | 291 | 292 | 293 | 294 | 295 | Prints the number of output multicast 296 | packets. 297 | 298 | 299 | 300 | 301 | 302 | 303 | Prints the number of bytes of 304 | incoming traffic measured in one second. 305 | 306 | 307 | 308 | 309 | 310 | 311 | Prints the number of bytes of 312 | outgoing traffic measured in one second. 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | AUTHOR 321 | 322 | 323 | Benjamin BAYART 324 | 325 | 326 | 327 | -------------------------------------------------------------------------------- /is_utf8/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Julien Palard. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #define _POSIX_C_SOURCE 200809L 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "is_utf8.h" 38 | 39 | #define VERSION "1.2" 40 | #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) 41 | 42 | 43 | static int show_str(const char *str, unsigned int max_length) 44 | { 45 | int printed = 0; 46 | 47 | while (max_length-- > 0) 48 | { 49 | printed += printf("%c", (*str >= ' ' && *str <= '~') ? (unsigned char)*str: '.'); 50 | str += 1; 51 | } 52 | return printed; 53 | } 54 | 55 | static int show_hex_str(const char *str, unsigned int max_length) 56 | { 57 | int printed = 0; 58 | 59 | while (max_length-- > 0) 60 | printed += printf("%.2X ", (unsigned char)*str++); 61 | return printed; 62 | } 63 | 64 | /*show_context(, 5, 279, 2, chars_before_error: 8, chars_after_error: -274) 65 | **/ 66 | static void show_context(char *str, int str_length, int err_pos_in_str, int faulty_bytes) 67 | { 68 | int chars_before_error = MIN(err_pos_in_str, 8); 69 | int chars_after_error = MIN(str_length - err_pos_in_str, 8); 70 | int printed = 0; 71 | 72 | printed = show_hex_str(str + err_pos_in_str - chars_before_error, chars_before_error + chars_after_error); /* Print up to error. */ 73 | printf("%*s | ", 3 * 16 - printed, ""); 74 | show_str(str + err_pos_in_str - chars_before_error, chars_before_error + chars_after_error); /* Print up to error. */ 75 | printf("\n"); 76 | printed = printf("%*s", (3 * chars_before_error), ""); 77 | printed += printf("%.*s", faulty_bytes * 2 + faulty_bytes - 1, "^^^^^^^^^^^^^^^^"); 78 | printf("%*s | ", 3 * 16 - printed, ""); 79 | printf("%*s", (chars_before_error), ""); 80 | printf("%.*s", faulty_bytes, "^^^^"); 81 | printf("\n\n"); 82 | } 83 | 84 | static void print_utf8_error( 85 | const char* file_path, 86 | int error_line, int error_column, int byte_no, 87 | char *str, int str_length, int err_pos_in_str, 88 | const char *message, int faulty_bytes, 89 | int quiet, int verbose, 90 | int list_only, int invert) 91 | { 92 | if (quiet) 93 | return; 94 | if (message && !invert) 95 | { 96 | if (list_only) 97 | printf("%s\n", file_path); 98 | else 99 | printf("%s: line %d, char %d, byte %d: %s\n", 100 | file_path, error_line, error_column, byte_no, 101 | message); 102 | if (verbose && !list_only) 103 | { 104 | show_context(str, str_length, err_pos_in_str, faulty_bytes); 105 | } 106 | } 107 | if (!message && invert) 108 | { 109 | printf("%s\n", file_path); 110 | } 111 | } 112 | 113 | #define handle_error(msg, target) \ 114 | do {retval = EXIT_FAILURE; perror(msg); goto target;} while (0) 115 | 116 | static int is_utf8_readline(FILE *stream, const char *file_path, 117 | int quiet, int verbose, int list_only, int invert) 118 | { 119 | char *string = NULL; 120 | size_t size = 0; 121 | ssize_t str_length; 122 | char *message = NULL; 123 | int lineno = 1; 124 | int pos = 0; 125 | int offset = 0; 126 | int faulty_bytes = 0; 127 | 128 | while ((str_length = getline(&string, &size, stream)) != -1) 129 | { 130 | pos = is_utf8((unsigned char*)string, str_length, &message, &faulty_bytes); 131 | if (message != NULL) 132 | { 133 | offset += pos; 134 | print_utf8_error(file_path, lineno, pos, offset, 135 | string, str_length, pos, message, faulty_bytes, 136 | quiet, verbose, list_only, invert); 137 | break; 138 | } 139 | offset += str_length; 140 | lineno += 1; 141 | } 142 | if (string != NULL) 143 | free(string); 144 | return message == NULL ? EXIT_SUCCESS : EXIT_FAILURE; 145 | } 146 | 147 | static void count_lines(const char *string, int length, int up_to, int *line, int *column) 148 | { 149 | int pos = 0; 150 | int line_start_at = 0; 151 | 152 | *line = 1; 153 | while (pos < length && pos < up_to) 154 | { 155 | if (string[pos] == '\n') 156 | { 157 | line_start_at = pos + 1; 158 | *line += 1; 159 | } 160 | pos += 1; 161 | } 162 | *column = 1 + up_to - line_start_at; 163 | } 164 | 165 | static int is_utf8_mmap(const char *file_path, int quiet, int verbose, 166 | int list_only, int invert) 167 | { 168 | char *addr; 169 | struct stat sb; 170 | int fd; 171 | int pos = 0; 172 | char *message; 173 | int retval = EXIT_SUCCESS; 174 | int error_column = 1; 175 | int error_line = 0; 176 | int faulty_bytes = 0; 177 | 178 | fd = open(file_path, O_RDONLY); 179 | if (fd == -1) 180 | handle_error("open", err_open); 181 | if (fstat(fd, &sb) == -1) /* To obtain file size */ 182 | handle_error("fstat", err_fstat); 183 | addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 184 | if (addr == MAP_FAILED) 185 | { 186 | /* Can't nmap, maybe a pipe or whatever, let's try readline. */ 187 | close(fd); 188 | return is_utf8_readline(fopen(file_path, "r"), file_path, 189 | quiet, verbose, list_only, invert); 190 | } 191 | pos = is_utf8((unsigned char*)addr, sb.st_size, &message, &faulty_bytes); 192 | if (message != NULL) 193 | count_lines(addr, sb.st_size, pos, &error_line, &error_column); 194 | print_utf8_error(file_path, error_line, error_column, pos, 195 | addr, sb.st_size, pos, message, faulty_bytes, 196 | quiet, verbose, list_only, invert); 197 | if (message != NULL) 198 | retval = EXIT_FAILURE; 199 | munmap(addr, sb.st_size); 200 | err_fstat: 201 | close(fd); 202 | err_open: 203 | return retval; 204 | } 205 | 206 | static void usage(const char *program_name) { 207 | printf("Usage: %s [OPTION]... [FILE]...\n" 208 | "Check whether input files are valid UTF-8.\n" 209 | "\n" 210 | " -h, --help display this help text and exit\n" 211 | " -q, --quiet suppress all normal output\n" 212 | " -l, --list print only names of FILEs containing invalid UTF-8\n" 213 | " -i, --invert list valid UTF-8 files instead of invalid ones\n" 214 | " -v, --verbose print detailed error (multiple lines)\n" 215 | "\n" 216 | "This is version %s.\n", 217 | program_name, VERSION); 218 | } 219 | 220 | int main(int ac, char **av) 221 | { 222 | int quiet = 0; 223 | int exit_value = EXIT_SUCCESS; 224 | int i; 225 | int list_only = 0; 226 | int invert = 0; 227 | int verbose = 0; 228 | int opt; 229 | struct option options[] = { 230 | { "help", no_argument, NULL, 'h' }, 231 | { "quiet", no_argument, &quiet, 1 }, 232 | { "list-only", no_argument, &list_only, 1 }, 233 | { "invert", no_argument, &invert, 1 }, 234 | { "verbose", no_argument, &verbose, 1 }, 235 | { 0, 0, 0, 0 } 236 | }; 237 | 238 | while ((opt = getopt_long(ac, av, "hqliv", options, NULL)) != -1) { 239 | switch (opt) { 240 | case 0: 241 | break; 242 | 243 | case 'h': 244 | usage(av[0]); 245 | return EXIT_SUCCESS; 246 | 247 | case 'q': 248 | quiet = 1; 249 | break; 250 | 251 | case 'l': 252 | list_only = 1; 253 | break; 254 | 255 | case 'i': 256 | invert = 1; 257 | break; 258 | 259 | case 'v': 260 | verbose = 1; 261 | break; 262 | 263 | case '?': 264 | usage(av[0]); 265 | return EXIT_FAILURE; 266 | 267 | default: 268 | usage(av[0]); 269 | return EXIT_FAILURE; 270 | } 271 | } 272 | if (optind == ac) 273 | { 274 | return is_utf8_readline(stdin, "(standard input)", quiet, verbose, 275 | list_only, invert); 276 | } 277 | else 278 | { 279 | for (i = optind; i < ac; ++i) 280 | { 281 | if (is_utf8_mmap(av[i], quiet, verbose, 282 | list_only, invert) == EXIT_FAILURE) 283 | exit_value = EXIT_FAILURE; 284 | } 285 | return exit_value; 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /parallel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * parallel.c - run commands in parallel until you run out of commands 3 | * 4 | * Copyright © 2008 Tollef Fog Heen 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * version 2 as published by the Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18 | * USA 19 | * 20 | */ 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #ifdef __sun 38 | # include /* getloadavg() */ 39 | #endif 40 | 41 | #if !defined(WEXITED) 42 | #define WEXITED 0 43 | #endif 44 | 45 | static pid_t pipe_child_stdout = 0; 46 | static pid_t pipe_child_stderr = 0; 47 | 48 | void usage() { 49 | printf("parallel [OPTIONS] command -- arguments\n\tfor each argument, " 50 | "run command with argument, in parallel\n"); 51 | printf("parallel [OPTIONS] -- commands\n\trun specified commands in parallel\n"); 52 | exit(1); 53 | } 54 | 55 | static void redirect(int fd, int target_fd, const char *name) 56 | { 57 | if (fd == target_fd) 58 | return; 59 | 60 | if (dup2(fd, target_fd) < 0) { 61 | fprintf(stderr, "unable to open %s from internal pipe: %s\n", 62 | name, strerror(errno)); 63 | exit(1); 64 | } 65 | close(fd); 66 | } 67 | 68 | void exec_child(char **command, char **arguments, int replace_cb, int nargs, 69 | int stdout_fd, int stderr_fd) 70 | { 71 | if (fork() != 0) { 72 | return; 73 | } 74 | 75 | redirect(stdout_fd, 1, "stdout"); 76 | redirect(stderr_fd, 2, "stderr"); 77 | 78 | if (command[0]) { 79 | char **argv; 80 | int argc = 0; 81 | int i; 82 | char *s; 83 | 84 | while (command[argc] != 0) { 85 | argc++; 86 | } 87 | if (! replace_cb) 88 | argc++; 89 | argv = calloc(sizeof(char*), argc + nargs); 90 | 91 | for (i = 0; i < argc; i++) { 92 | while (replace_cb && (s=strstr(command[i], "{}"))) { 93 | char *buf=malloc(strlen(command[i]) + strlen(arguments[0])); 94 | s[0]='\0'; 95 | sprintf(buf, "%s%s%s", command[i], arguments[0], s+2); 96 | command[i]=buf; 97 | } 98 | argv[i] = command[i]; 99 | } 100 | if (! replace_cb) 101 | memcpy(argv + i - 1, arguments, nargs * sizeof(char *)); 102 | execvp(argv[0], argv); 103 | exit(1); 104 | } 105 | else { 106 | int ret=system(arguments[0]); 107 | if (WIFEXITED(ret)) { 108 | exit(WEXITSTATUS(ret)); 109 | } 110 | else { 111 | exit(1); 112 | } 113 | } 114 | return; 115 | } 116 | 117 | #if defined(__CYGWIN__) 118 | typedef enum { 119 | P_ALL, 120 | P_PID, 121 | P_PGID 122 | } idtype_t; 123 | int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) { 124 | pid_t pid; 125 | switch (idtype) { 126 | case P_PID: 127 | pid = id; 128 | break; 129 | case P_PGID: 130 | pid = -id; 131 | break; 132 | case P_ALL: 133 | pid = -1; 134 | break; 135 | default: 136 | errno = EINVAL; 137 | return -1; 138 | } 139 | int status; 140 | pid = waitpid(pid, &status, WEXITED | options); 141 | if (pid == -1) { 142 | return -1; 143 | } 144 | infop->si_pid = pid; 145 | infop->si_signo = SIGCHLD; 146 | if (WIFEXITED(status)) { 147 | infop->si_code = CLD_EXITED; 148 | infop->si_status = WEXITSTATUS(status); 149 | } 150 | else if (WIFSIGNALED(status)) { 151 | infop->si_code = CLD_KILLED; 152 | infop->si_status = WTERMSIG(status); 153 | #ifdef WCOREDUMP 154 | if (WCOREDUMP(status)) { 155 | infop->si_code = CLD_DUMPED; 156 | } 157 | #endif 158 | } 159 | else if (WIFSTOPPED(status)) { 160 | infop->si_code = CLD_STOPPED; 161 | infop->si_status = WSTOPSIG(status); 162 | } 163 | else if (WIFCONTINUED(status)) { 164 | infop->si_code = CLD_CONTINUED; 165 | infop->si_status = SIGCONT; 166 | } 167 | return 0; 168 | } 169 | #endif 170 | 171 | int wait_for_child(int options) { 172 | id_t id_ignored = 0; 173 | siginfo_t infop; 174 | 175 | infop.si_pid = 0; 176 | waitid(P_ALL, id_ignored, &infop, WEXITED | options); 177 | if (infop.si_pid == 0) { 178 | return -1; /* Nothing to wait for */ 179 | } 180 | if (infop.si_code == CLD_EXITED) { 181 | return infop.si_status; 182 | } 183 | return 1; 184 | } 185 | 186 | static int pipe_child(int fd, int orig_fd) 187 | { 188 | const char *fd_info = (orig_fd == 1) ? "out" : "err"; 189 | char buf[4096]; 190 | int r; 191 | 192 | while ((r = read(fd, buf, sizeof(buf))) >= 0) { 193 | int w; 194 | int len; 195 | 196 | len = r; 197 | 198 | do { 199 | w = write(orig_fd, buf, len); 200 | if (w < 0) { 201 | fprintf(stderr, "unable to write to std%s: " 202 | "%s\n", fd_info, strerror(errno)); 203 | exit(1); 204 | } 205 | 206 | len -= w; 207 | } while (len > 0); 208 | } 209 | 210 | fprintf(stderr, "unable to read from std%s: %s\n", fd_info, 211 | strerror(errno)); 212 | exit(1); 213 | } 214 | 215 | pid_t create_pipe_child(int *fd, int orig_fd) 216 | { 217 | int fds[2]; 218 | pid_t pid; 219 | 220 | if (pipe(fds)) { 221 | fprintf(stderr, "unable to create pipe: %s\n", 222 | strerror(errno)); 223 | exit(1); 224 | } 225 | 226 | *fd = fds[1]; 227 | 228 | pid = fork(); 229 | if (pid < 0) { 230 | fprintf(stderr, "unable to fork: %s\n", strerror(errno)); 231 | return pid; 232 | } 233 | 234 | if (pid) { 235 | close(fds[0]); 236 | return pid; 237 | } 238 | 239 | close(fds[1]); 240 | 241 | return pipe_child(fds[0], orig_fd); 242 | } 243 | 244 | #if defined(__CYGWIN__) || defined(__UCLIBC__) 245 | int getloadavg(double loadavg[], int nelem) { 246 | int fd, n, elem; 247 | char buf[128]; 248 | char const* p = buf; 249 | fd = open("/proc/loadavg", O_RDONLY); 250 | if (fd == -1) { 251 | return -1; 252 | } 253 | n = read(fd, buf, sizeof(buf)-1); 254 | if (close(fd) == -1 || n == -1) { 255 | return -1; 256 | } 257 | buf[n] = '\0'; 258 | for (elem = 0; elem < nelem; elem++) { 259 | char* end; 260 | double d = strtod(p, &end); 261 | if (p == end) { 262 | break; 263 | } 264 | loadavg[elem] = d; 265 | p = end; 266 | } 267 | return elem == 0 ? -1 : elem; 268 | } 269 | #endif 270 | 271 | int main(int argc, char **argv) { 272 | int maxjobs = -1; 273 | int curjobs = 0; 274 | double maxload = -1; 275 | int argsatonce = 1; 276 | int opt; 277 | char **command = calloc(sizeof(char*), argc); 278 | char **arguments = NULL; 279 | int argidx = 0; 280 | int arglen = 0; 281 | int cidx = 0; 282 | int returncode = 0; 283 | int replace_cb = 0; 284 | int stdout_fd = 1; 285 | int stderr_fd = 2; 286 | char *t; 287 | 288 | while ((argv[optind] && strcmp(argv[optind], "--") != 0) && 289 | (opt = getopt(argc, argv, "+hij:l:n:")) != -1) { 290 | switch (opt) { 291 | case 'h': 292 | usage(); 293 | break; 294 | case 'i': 295 | replace_cb = 1; 296 | break; 297 | case 'j': 298 | errno = 0; 299 | maxjobs = strtoul(optarg, &t, 0); 300 | if (errno != 0 || (t-optarg) != strlen(optarg)) { 301 | fprintf(stderr, "option '%s' is not a number\n", 302 | optarg); 303 | exit(2); 304 | } 305 | break; 306 | case 'l': 307 | errno = 0; 308 | maxload = strtod(optarg, &t); 309 | if (errno != 0 || (t-optarg) != strlen(optarg)) { 310 | fprintf(stderr, "option '%s' is not a number\n", 311 | optarg); 312 | exit(2); 313 | } 314 | break; 315 | case 'n': 316 | errno = 0; 317 | argsatonce = strtoul(optarg, &t, 0); 318 | if (errno != 0 || argsatonce < 1 || (t-optarg) != strlen(optarg)) { 319 | fprintf(stderr, "option '%s' is not a positive number\n", 320 | optarg); 321 | exit(2); 322 | } 323 | break; 324 | default: /* ’?’ */ 325 | usage(); 326 | break; 327 | } 328 | } 329 | 330 | if (replace_cb && argsatonce > 1) { 331 | fprintf(stderr, "options -i and -n are incompatible\n"); 332 | exit(2); 333 | } 334 | 335 | if (maxjobs < 0) { 336 | #ifdef _SC_NPROCESSORS_ONLN 337 | maxjobs = sysconf(_SC_NPROCESSORS_ONLN); 338 | #else 339 | #warning Cannot autodetect number of CPUS on this system: _SC_NPROCESSORS_ONLN not defined. 340 | maxjobs = 1; 341 | #endif 342 | } 343 | 344 | while (optind < argc) { 345 | if (strcmp(argv[optind], "--") == 0) { 346 | int i; 347 | 348 | optind++; 349 | arglen = argc - optind; 350 | arguments = calloc(sizeof(char *), arglen); 351 | if (! arguments) { 352 | exit(1); 353 | } 354 | 355 | for (i = 0; i < arglen; i++) { 356 | arguments[i] = strdup(argv[optind + i]); 357 | } 358 | optind += i; 359 | } 360 | else { 361 | command[cidx] = strdup(argv[optind]); 362 | cidx++; 363 | } 364 | optind++; 365 | } 366 | 367 | if (argsatonce > 1 && ! command[0]) { 368 | fprintf(stderr, "option -n cannot be used without a command\n"); 369 | exit(2); 370 | } 371 | 372 | pipe_child_stdout = create_pipe_child(&stdout_fd, 1); 373 | pipe_child_stderr = create_pipe_child(&stderr_fd, 2); 374 | 375 | if ((pipe_child_stdout < 0) || (pipe_child_stderr < 0)) 376 | exit(1); 377 | 378 | while (argidx < arglen) { 379 | double load; 380 | 381 | getloadavg(&load, 1); 382 | 383 | if ((maxjobs == 0 || curjobs < maxjobs) && 384 | (maxload < 0 || load < maxload)) { 385 | 386 | if (argsatonce > arglen - argidx) 387 | argsatonce = arglen - argidx; 388 | exec_child(command, arguments + argidx, 389 | replace_cb, argsatonce, stdout_fd, 390 | stderr_fd); 391 | argidx += argsatonce; 392 | curjobs++; 393 | } 394 | 395 | if (maxjobs == 0 || curjobs == maxjobs) { 396 | returncode |= wait_for_child(0); 397 | curjobs--; 398 | } 399 | 400 | if (maxload > 0 && load >= maxload) { 401 | int r; 402 | sleep(1); /* XXX We should have a better 403 | * heurestic than this */ 404 | r = wait_for_child(WNOHANG); 405 | if (r > 0) 406 | returncode |= r; 407 | if (r != -1) 408 | curjobs--; 409 | } 410 | } 411 | while (curjobs > 0) { 412 | returncode |= wait_for_child(0); 413 | curjobs--; 414 | } 415 | 416 | if (pipe_child_stdout) { 417 | kill(pipe_child_stdout, SIGKILL); 418 | wait_for_child(0); 419 | } 420 | if (pipe_child_stderr) { 421 | kill(pipe_child_stderr, SIGKILL); 422 | wait_for_child(0); 423 | } 424 | 425 | return returncode; 426 | } 427 | 428 | -------------------------------------------------------------------------------- /sponge.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sponge.c - read in all available info from stdin, then output it to 3 | * file named on the command line 4 | * 5 | * Copyright © 2006 Tollef Fog Heen 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * version 2 as published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 19 | * USA 20 | * 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | /* MAX() */ 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | /* SIZE_MAX */ 35 | #include 36 | #include 37 | #include 38 | 39 | #include "physmem.c" 40 | 41 | #define BUFF_SIZE 8192 42 | #define MIN_SPONGE_SIZE BUFF_SIZE 43 | char *tmpname = NULL; 44 | 45 | void usage() { 46 | printf("sponge [-a] : soak up all input from stdin and write it " 47 | "to \n"); 48 | exit(0); 49 | } 50 | 51 | /* all the signal stuff copied from gnu sort */ 52 | 53 | /* The set of signals that are caught. */ 54 | static sigset_t caught_signals; 55 | 56 | /* Critical section status. */ 57 | struct cs_status { 58 | int valid; // was bool 59 | sigset_t sigs; 60 | }; 61 | 62 | /* Enter a critical section. */ 63 | static struct cs_status cs_enter (void) { 64 | struct cs_status status; 65 | status.valid = (sigprocmask(SIG_BLOCK, &caught_signals, &status.sigs) == 0); 66 | return status; 67 | } 68 | 69 | /* Leave a critical section. */ 70 | static void cs_leave (struct cs_status status) { 71 | if (status.valid) { 72 | /* Ignore failure when restoring the signal mask. */ 73 | sigprocmask(SIG_SETMASK, &status.sigs, NULL); 74 | } 75 | } 76 | 77 | static void cleanup () { 78 | if (tmpname) { 79 | unlink(tmpname); 80 | } 81 | } 82 | 83 | static void onexit_cleanup (void) { 84 | struct cs_status cs = cs_enter(); 85 | cleanup(); 86 | cs_leave(cs); 87 | } 88 | 89 | static void sighandler (int sig) { 90 | if (! SA_NOCLDSTOP) 91 | signal(sig, SIG_IGN); 92 | 93 | cleanup(); 94 | 95 | signal(sig, SIG_DFL); 96 | raise(sig); 97 | } 98 | 99 | /* taken from coreutils sort */ 100 | static size_t default_sponge_size (void) { 101 | /* Let MEM be available memory or 1/8 of total memory, whichever 102 | is greater. */ 103 | double avail = physmem_available(); 104 | double total = physmem_total(); 105 | double mem = MAX(avail, total / 8); 106 | struct rlimit rlimit; 107 | 108 | /* Let SIZE be MEM, but no more than the maximum object size or 109 | system resource limits. Avoid the MIN macro here, as it is not 110 | quite right when only one argument is floating point. Don't 111 | bother to check for values like RLIM_INFINITY since in practice 112 | they are not much less than SIZE_MAX. */ 113 | size_t size = SIZE_MAX; 114 | if (mem < size) 115 | size = mem; 116 | if (getrlimit(RLIMIT_DATA, &rlimit) == 0 && rlimit.rlim_cur < size) 117 | size = rlimit.rlim_cur; 118 | #ifdef RLIMIT_AS 119 | if (getrlimit(RLIMIT_AS, &rlimit) == 0 && rlimit.rlim_cur < size) 120 | size = rlimit.rlim_cur; 121 | #endif 122 | 123 | /* Leave a large safety margin for the above limits, as failure can 124 | occur when they are exceeded. */ 125 | size /= 2; 126 | 127 | #ifdef RLIMIT_RSS 128 | /* Leave a 1/16 margin for RSS to leave room for code, stack, etc. 129 | Exceeding RSS is not fatal, but can be quite slow. */ 130 | if (getrlimit(RLIMIT_RSS, &rlimit) == 0 && rlimit.rlim_cur / 16 * 15 < size) 131 | size = rlimit.rlim_cur / 16 * 15; 132 | #endif 133 | 134 | /* Use no less than the minimum. */ 135 | return MAX (size, MIN_SPONGE_SIZE); 136 | } 137 | 138 | void trapsignals (void) { 139 | ssize_t i = 0; 140 | static int const sig[] = { 141 | /* The usual suspects. */ 142 | SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM, 143 | #ifdef SIGPOLL 144 | SIGPOLL, 145 | #endif 146 | #ifdef SIGPROF 147 | SIGPROF, 148 | #endif 149 | #ifdef SIGVTALRM 150 | SIGVTALRM, 151 | #endif 152 | #ifdef SIGXCPU 153 | SIGXCPU, 154 | #endif 155 | #ifdef SIGXFSZ 156 | SIGXFSZ, 157 | #endif 158 | }; 159 | int nsigs = sizeof(sig) / sizeof(sig[0]); 160 | 161 | #if SA_NOCLDSTOP 162 | struct sigaction act; 163 | 164 | sigemptyset(&caught_signals); 165 | for (i = 0; i < nsigs; i++) { 166 | sigaction(sig[i], NULL, &act); 167 | if (act.sa_handler != SIG_IGN) 168 | sigaddset(&caught_signals, sig[i]); 169 | } 170 | 171 | act.sa_handler = sighandler; 172 | act.sa_mask = caught_signals; 173 | act.sa_flags = 0; 174 | 175 | for (i = 0; i < nsigs; i++) 176 | if (sigismember(&caught_signals, sig[i])) 177 | sigaction(sig[i], &act, NULL); 178 | #else 179 | for (i = 0; i < nsigs; i++) 180 | if (signal(sig[i], SIG_IGN) != SIG_IGN) { 181 | signal(sig[i], sighandler); 182 | siginterrupt (sig[i], 1); 183 | } 184 | #endif 185 | } 186 | 187 | static void write_buff_tmp(char* buff, size_t length, FILE *fd) { 188 | if (fwrite(buff, length, 1, fd) < 1) { 189 | perror("error writing buffer to temporary file"); 190 | fclose(fd); 191 | exit(1); 192 | } 193 | } 194 | 195 | static void write_buff_tmp_finish (char* buff, size_t length, FILE *fd) { 196 | if (length) 197 | write_buff_tmp(buff, length, fd); 198 | if (fflush(fd) != 0) { 199 | perror("fflush"); 200 | exit(1); 201 | } 202 | } 203 | 204 | static void write_buff_out (char* buff, size_t length, FILE *fd) { 205 | if (fwrite(buff, length, 1, fd) < 1) { 206 | perror("error writing buffer to output file"); 207 | fclose(fd); 208 | exit(1); 209 | } 210 | } 211 | 212 | static void copy_file (FILE *infile, FILE *outfile, char *buf, size_t size) { 213 | ssize_t i; 214 | while ((i = read(fileno(infile), buf, size)) > 0) { 215 | write_buff_out(buf, i, outfile); 216 | } 217 | if (i == -1) { 218 | perror("read file"); 219 | fclose(infile); 220 | exit(1); 221 | } 222 | } 223 | 224 | static void copy_tmpfile (FILE *tmpfile, FILE *outfile, char *buf, size_t size) { 225 | if (lseek(fileno(tmpfile), 0, SEEK_SET)) { 226 | perror("could to seek to start of file"); 227 | fclose(tmpfile); 228 | exit(1); 229 | } 230 | copy_file(tmpfile, outfile, buf, size); 231 | if (fclose(tmpfile) != 0) { 232 | perror("read temporary file"); 233 | exit(1); 234 | } 235 | if (fclose(outfile) != 0) { 236 | perror("error writing buffer to output file"); 237 | exit(1); 238 | } 239 | } 240 | 241 | FILE *open_tmpfile (void) { 242 | struct cs_status cs; 243 | int tmpfd; 244 | FILE *tmpfile; 245 | mode_t mask; 246 | char *tmpdir; 247 | char const * const template="%s/sponge.XXXXXX"; 248 | 249 | trapsignals(); 250 | cs = cs_enter(); 251 | tmpdir = getenv("TMPDIR"); 252 | if (tmpdir == NULL) 253 | tmpdir = "/tmp"; 254 | /* Subtract 2 for `%s' and add 1 for the trailing NULL. */ 255 | tmpname=malloc(strlen(tmpdir) + strlen(template) - 2 + 1); 256 | if (! tmpname) { 257 | perror("failed to allocate memory"); 258 | exit(1); 259 | } 260 | sprintf(tmpname, template, tmpdir); 261 | mask=umask(077); 262 | tmpfd = mkstemp(tmpname); 263 | umask(mask); 264 | atexit(onexit_cleanup); // solaris on_exit(onexit_cleanup, 0); 265 | cs_leave(cs); 266 | 267 | if (tmpfd < 0) { 268 | perror("mkstemp failed"); 269 | exit(1); 270 | } 271 | tmpfile = fdopen(tmpfd, "w+"); 272 | if (! tmpfile) { 273 | perror("fdopen"); 274 | exit(1); 275 | } 276 | return tmpfile; 277 | } 278 | 279 | int main (int argc, char **argv) { 280 | char *buf, *bufstart, *outname = NULL; 281 | size_t bufsize = BUFF_SIZE; 282 | size_t bufused = 0; 283 | FILE *outfile, *tmpfile = 0; 284 | ssize_t i = 0; 285 | size_t mem_available = default_sponge_size(); 286 | int tmpfile_used=0; 287 | int append=0; 288 | int opt; 289 | 290 | while ((opt = getopt(argc, argv, "ha")) != -1) { 291 | switch (opt) { 292 | case 'h': 293 | usage(); 294 | break; 295 | case 'a': 296 | append=1; 297 | } 298 | } 299 | if (optind < argc) 300 | outname = argv[optind]; 301 | 302 | tmpfile = open_tmpfile(); 303 | bufstart = buf = malloc(bufsize); 304 | if (!buf) { 305 | perror("failed to allocate memory"); 306 | exit(1); 307 | } 308 | while ((i = read(0, buf, bufsize - bufused)) > 0) { 309 | bufused = bufused+i; 310 | if (bufused == bufsize) { 311 | if ((bufsize*2) >= mem_available) { 312 | write_buff_tmp(bufstart, bufused, tmpfile); 313 | bufused = 0; 314 | tmpfile_used = 1; 315 | } 316 | else { 317 | bufsize *= 2; 318 | bufstart = realloc(bufstart, bufsize); 319 | if (!bufstart) { 320 | perror("failed to realloc memory"); 321 | exit(1); 322 | } 323 | } 324 | } 325 | buf = bufstart + bufused; 326 | } 327 | if (i < 0) { 328 | perror("failed to read from stdin"); 329 | exit(1); 330 | } 331 | 332 | if (outname) { 333 | mode_t mode; 334 | struct stat statbuf; 335 | int exists = (lstat(outname, &statbuf) == 0); 336 | int regfile = exists && S_ISREG(statbuf.st_mode) && ! S_ISLNK(statbuf.st_mode); 337 | 338 | if (append && regfile) { 339 | char *tmpbuf = malloc(bufsize); 340 | if (!tmpbuf) { 341 | perror("failed to allocate memory"); 342 | exit(1); 343 | } 344 | outfile = fopen(outname, "r"); 345 | copy_file(outfile, tmpfile, tmpbuf, bufsize); 346 | fclose(outfile); 347 | } 348 | 349 | write_buff_tmp_finish(bufstart, bufused, tmpfile); 350 | 351 | /* Set temp file mode to match either 352 | * the old file mode, or the default file 353 | * mode for a newly created file. */ 354 | if (exists) { 355 | mode = statbuf.st_mode; 356 | } 357 | else { 358 | mode_t mask = umask(0); 359 | umask(mask); 360 | mode = 0666 & ~mask; 361 | } 362 | if (chmod(tmpname, mode) != 0) { 363 | perror("chmod"); 364 | exit(1); 365 | } 366 | 367 | /* If it's a regular file, or does not yet exist, 368 | * attempt a fast rename of the temp file. */ 369 | if ((regfile || ! exists) && 370 | rename(tmpname, outname) == 0) { 371 | tmpname=NULL; /* don't try to cleanup tmpname */ 372 | } 373 | else { 374 | /* Fall back to slow copy. */ 375 | outfile = fopen(outname, "w"); 376 | if (!outfile) { 377 | perror("error opening output file"); 378 | exit(1); 379 | } 380 | copy_tmpfile(tmpfile, outfile, bufstart, bufsize); 381 | } 382 | } 383 | else { 384 | if (tmpfile_used) { 385 | write_buff_tmp_finish(bufstart, bufused, tmpfile); 386 | copy_tmpfile(tmpfile, stdout, bufstart, bufsize); 387 | } 388 | else if (bufused) { 389 | /* buffer direct to stdout, no tmpfile */ 390 | write_buff_out(bufstart, bufused, stdout); 391 | } 392 | } 393 | 394 | return 0; 395 | } 396 | -------------------------------------------------------------------------------- /is_utf8/is_utf8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Julien Palard. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "is_utf8.h" 27 | 28 | /* 29 | Check if the given unsigned char * is a valid utf-8 sequence. 30 | 31 | Return value : 32 | If the string is valid utf-8, 0 is returned. 33 | Else the position, starting from 1, is returned. 34 | 35 | Source: 36 | http://www.unicode.org/versions/Unicode7.0.0/UnicodeStandard-7.0.pdf 37 | page 124, 3.9 "Unicode Encoding Forms", "UTF-8" 38 | 39 | 40 | Table 3-7. Well-Formed UTF-8 Byte Sequences 41 | ----------------------------------------------------------------------------- 42 | | Code Points | First Byte | Second Byte | Third Byte | Fourth Byte | 43 | | U+0000..U+007F | 00..7F | | | | 44 | | U+0080..U+07FF | C2..DF | 80..BF | | | 45 | | U+0800..U+0FFF | E0 | A0..BF | 80..BF | | 46 | | U+1000..U+CFFF | E1..EC | 80..BF | 80..BF | | 47 | | U+D000..U+D7FF | ED | 80..9F | 80..BF | | 48 | | U+E000..U+FFFF | EE..EF | 80..BF | 80..BF | | 49 | | U+10000..U+3FFFF | F0 | 90..BF | 80..BF | 80..BF | 50 | | U+40000..U+FFFFF | F1..F3 | 80..BF | 80..BF | 80..BF | 51 | | U+100000..U+10FFFF | F4 | 80..8F | 80..BF | 80..BF | 52 | ----------------------------------------------------------------------------- 53 | 54 | Returns the first erroneous byte position, and give in 55 | `faulty_bytes` the number of actually existing bytes taking part in this error. 56 | */ 57 | int is_utf8(unsigned char *str, size_t len, char **message, int *faulty_bytes) 58 | { 59 | size_t i = 0; 60 | 61 | *message = NULL; 62 | *faulty_bytes = 0; 63 | while (i < len) 64 | { 65 | if (str[i] <= 0x7F) /* 00..7F */ 66 | { 67 | i += 1; 68 | } 69 | else if (str[i] >= 0xC2 && str[i] <= 0xDF) /* C2..DF 80..BF */ 70 | { 71 | if (i + 1 < len) /* Expect a 2nd byte */ 72 | { 73 | if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) 74 | { 75 | *message = "After a first byte between C2 and DF, expecting a 2nd byte between 80 and BF"; 76 | *faulty_bytes = 2; 77 | return i; 78 | } 79 | } 80 | else 81 | { 82 | *message = "After a first byte between C2 and DF, expecting a 2nd byte."; 83 | *faulty_bytes = 1; 84 | return i; 85 | } 86 | i += 2; 87 | } 88 | else if (str[i] == 0xE0) /* E0 A0..BF 80..BF */ 89 | { 90 | if (i + 2 < len) /* Expect a 2nd and 3rd byte */ 91 | { 92 | if (str[i + 1] < 0xA0 || str[i + 1] > 0xBF) 93 | { 94 | *message = "After a first byte of E0, expecting a 2nd byte between A0 and BF."; 95 | *faulty_bytes = 2; 96 | return i; 97 | } 98 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 99 | { 100 | *message = "After a first byte of E0, expecting a 3nd byte between 80 and BF."; 101 | *faulty_bytes = 3; 102 | return i; 103 | } 104 | } 105 | else 106 | { 107 | *message = "After a first byte of E0, expecting two following bytes."; 108 | *faulty_bytes = 1; 109 | return i; 110 | } 111 | i += 3; 112 | } 113 | else if (str[i] >= 0xE1 && str[i] <= 0xEC) /* E1..EC 80..BF 80..BF */ 114 | { 115 | if (i + 2 < len) /* Expect a 2nd and 3rd byte */ 116 | { 117 | if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) 118 | { 119 | *message = "After a first byte between E1 and EC, expecting the 2nd byte between 80 and BF."; 120 | *faulty_bytes = 2; 121 | return i; 122 | } 123 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 124 | { 125 | *message = "After a first byte between E1 and EC, expecting the 3rd byte between 80 and BF."; 126 | *faulty_bytes = 3; 127 | return i; 128 | } 129 | } 130 | else 131 | { 132 | *message = "After a first byte between E1 and EC, expecting two following bytes."; 133 | *faulty_bytes = 1; 134 | return i; 135 | } 136 | i += 3; 137 | } 138 | else if (str[i] == 0xED) /* ED 80..9F 80..BF */ 139 | { 140 | if (i + 2 < len) /* Expect a 2nd and 3rd byte */ 141 | { 142 | if (str[i + 1] < 0x80 || str[i + 1] > 0x9F) 143 | { 144 | *message = "After a first byte of ED, expecting 2nd byte between 80 and 9F."; 145 | *faulty_bytes = 2; 146 | return i; 147 | } 148 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 149 | { 150 | *message = "After a first byte of ED, expecting 3rd byte between 80 and BF."; 151 | *faulty_bytes = 3; 152 | return i; 153 | } 154 | } 155 | else 156 | { 157 | *message = "After a first byte of ED, expecting two following bytes."; 158 | *faulty_bytes = 1; 159 | return i; 160 | } 161 | i += 3; 162 | } 163 | else if (str[i] >= 0xEE && str[i] <= 0xEF) /* EE..EF 80..BF 80..BF */ 164 | { 165 | if (i + 2 < len) /* Expect a 2nd and 3rd byte */ 166 | { 167 | if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) 168 | { 169 | *message = "After a first byte between EE and EF, expecting 2nd byte between 80 and BF."; 170 | *faulty_bytes = 2; 171 | return i; 172 | } 173 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 174 | { 175 | *message = "After a first byte between EE and EF, expecting 3rd byte between 80 and BF."; 176 | *faulty_bytes = 3; 177 | return i; 178 | } 179 | } 180 | else 181 | { 182 | *message = "After a first byte between EE and EF, two following bytes."; 183 | *faulty_bytes = 1; 184 | return i; 185 | } 186 | i += 3; 187 | } 188 | else if (str[i] == 0xF0) /* F0 90..BF 80..BF 80..BF */ 189 | { 190 | if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */ 191 | { 192 | if (str[i + 1] < 0x90 || str[i + 1] > 0xBF) 193 | { 194 | *message = "After a first byte of F0, expecting 2nd byte between 90 and BF."; 195 | *faulty_bytes = 2; 196 | return i; 197 | } 198 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 199 | { 200 | *message = "After a first byte of F0, expecting 3rd byte between 80 and BF."; 201 | *faulty_bytes = 3; 202 | return i; 203 | } 204 | if (str[i + 3] < 0x80 || str[i + 3] > 0xBF) 205 | { 206 | *message = "After a first byte of F0, expecting 4th byte between 80 and BF."; 207 | *faulty_bytes = 4; 208 | return i; 209 | } 210 | } 211 | else 212 | { 213 | *message = "After a first byte of F0, expecting three following bytes."; 214 | *faulty_bytes = 1; 215 | return i; 216 | } 217 | i += 4; 218 | } 219 | else if (str[i] >= 0xF1 && str[i] <= 0xF3) /* F1..F3 80..BF 80..BF 80..BF */ 220 | { 221 | if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */ 222 | { 223 | if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) 224 | { 225 | *message = "After a first byte of F1, F2, or F3, expecting a 2nd byte between 80 and BF."; 226 | *faulty_bytes = 2; 227 | return i; 228 | } 229 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 230 | { 231 | *message = "After a first byte of F1, F2, or F3, expecting a 3rd byte between 80 and BF."; 232 | *faulty_bytes = 3; 233 | return i; 234 | } 235 | if (str[i + 3] < 0x80 || str[i + 3] > 0xBF) 236 | { 237 | *message = "After a first byte of F1, F2, or F3, expecting a 4th byte between 80 and BF."; 238 | *faulty_bytes = 4; 239 | return i; 240 | } 241 | } 242 | else 243 | { 244 | *message = "After a first byte of F1, F2, or F3, expecting three following bytes."; 245 | *faulty_bytes = 1; 246 | return i; 247 | } 248 | i += 4; 249 | } 250 | else if (str[i] == 0xF4) /* F4 80..8F 80..BF 80..BF */ 251 | { 252 | if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */ 253 | { 254 | if (str[i + 1] < 0x80 || str[i + 1] > 0x8F) 255 | { 256 | *message = "After a first byte of F4, expecting 2nd byte between 80 and 8F."; 257 | *faulty_bytes = 2; 258 | return i; 259 | } 260 | if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) 261 | { 262 | *message = "After a first byte of F4, expecting 3rd byte between 80 and BF."; 263 | *faulty_bytes = 3; 264 | return i; 265 | } 266 | if (str[i + 3] < 0x80 || str[i + 3] > 0xBF) 267 | { 268 | *message = "After a first byte of F4, expecting 4th byte between 80 and BF."; 269 | *faulty_bytes = 4; 270 | return i; 271 | } 272 | } 273 | else 274 | { 275 | *message = "After a first byte of F4, expecting three following bytes."; 276 | *faulty_bytes = 1; 277 | return i; 278 | } 279 | i += 4; 280 | } 281 | else 282 | { 283 | *message = "Expecting bytes in the following ranges: 00..7F C2..F4."; 284 | *faulty_bytes = 1; 285 | return i; 286 | } 287 | } 288 | message = NULL; 289 | return 0; 290 | } 291 | -------------------------------------------------------------------------------- /ifdata.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined(__linux__) 9 | #include 10 | #include 11 | #endif 12 | 13 | #if defined(__FreeBSD_kernel__) 14 | #include 15 | #endif 16 | 17 | #if defined(__GNU__) 18 | #include 19 | #endif 20 | 21 | #if defined(__APPLE__) || defined(__OpenBSD__) 22 | #define s6_addr16 __u6_addr.__u6_addr16 23 | #include 24 | #endif 25 | 26 | #if defined(__sun) 27 | #define s6_addr16 _S6_un._S6_u8 28 | #include 29 | #include 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | enum { 40 | DO_EXISTS = 1, 41 | DO_PEXISTS, 42 | DO_PADDRESS, 43 | DO_PMASK, 44 | DO_PMTU, 45 | DO_PCAST, 46 | DO_PALL, 47 | DO_PFLAGS, 48 | DO_SINPACKETS, 49 | DO_SINBYTES, 50 | DO_SINERRORS, 51 | DO_SINDROPS, 52 | DO_SINALL, 53 | DO_SINFIFO, 54 | DO_SINFRAME, 55 | DO_SINCOMPRESSES, 56 | DO_SINMULTICAST, 57 | DO_SOUTALL, 58 | DO_SOUTBYTES, 59 | DO_SOUTPACKETS, 60 | DO_SOUTERRORS, 61 | DO_SOUTDROPS, 62 | DO_SOUTFIFO, 63 | DO_SOUTCOLLS, 64 | DO_SOUTCARRIER, 65 | DO_SOUTMULTICAST, 66 | DO_PNETWORK, 67 | DO_PHWADDRESS, 68 | DO_BIPS, 69 | DO_BOPS 70 | }; 71 | 72 | struct if_stat { 73 | unsigned long long in_packets, in_bytes, in_errors, in_drops; 74 | unsigned long long in_fifo, in_frame, in_compress, in_multicast; 75 | unsigned long long out_bytes, out_packets, out_errors, out_drops; 76 | unsigned long long out_fifo, out_colls, out_carrier, out_multicast; 77 | }; 78 | 79 | 80 | void print_quad_ipv4(in_addr_t i) { 81 | i = ntohl(i); 82 | printf("%d.%d.%d.%d", 83 | (i & 0xff000000) >> 24, 84 | (i & 0x00ff0000) >> 16, 85 | (i & 0x0000ff00) >> 8, 86 | (i & 0x000000ff)); 87 | } 88 | 89 | void print_quad_ipv6(uint16_t *a) { 90 | printf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", 91 | a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); 92 | } 93 | 94 | void print_quad(struct sockaddr *adr) { 95 | switch (adr->sa_family) { 96 | case AF_INET: 97 | print_quad_ipv4(((struct sockaddr_in*)adr)->sin_addr.s_addr); 98 | break; 99 | case AF_INET6: 100 | print_quad_ipv6(((struct sockaddr_in6*)adr)->sin6_addr.s6_addr16); 101 | break; 102 | default: 103 | printf("NON-IP"); 104 | break; 105 | } 106 | } 107 | 108 | enum print_error_enum { 109 | PRINT_ERROR, 110 | PRINT_NO_ERROR, 111 | }; 112 | 113 | /** 114 | * return 0 success 115 | * 1 error 116 | */ 117 | static int do_socket_ioctl(const char *ifname, const unsigned long int request, 118 | struct ifreq *req, int *ioctl_errno, 119 | const enum print_error_enum print_error) { 120 | int sock, res; 121 | 122 | if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1) 123 | return 1; 124 | strncpy(req->ifr_name, ifname, IFNAMSIZ); 125 | req->ifr_name[IFNAMSIZ - 1] = 0; 126 | 127 | if ((res = ioctl(sock, request, req)) == -1) { 128 | if (ioctl_errno) 129 | *ioctl_errno = errno; 130 | if (print_error == PRINT_ERROR) { 131 | if (errno == ENODEV) { 132 | fprintf(stderr, "No such network interface: %s\n", ifname); 133 | exit(1); 134 | } 135 | else 136 | fprintf(stderr, "ioctl on %s: %s\n", ifname, 137 | strerror(errno)); 138 | } 139 | close(sock); 140 | return 1; 141 | } 142 | 143 | close(sock); 144 | 145 | return 0; 146 | } 147 | 148 | int if_exists(const char *iface) { 149 | struct ifreq r; 150 | return !do_socket_ioctl(iface, SIOCGIFFLAGS, &r, NULL, PRINT_NO_ERROR); 151 | } 152 | 153 | #if defined(__linux__) 154 | 155 | void if_flags(const char *iface) { 156 | struct ifreq r; 157 | unsigned int i; 158 | const struct { 159 | unsigned int flag; 160 | char *name; 161 | } flags[] = { 162 | { IFF_UP, "Up" }, 163 | { IFF_BROADCAST, "Broadcast" }, 164 | { IFF_DEBUG, "Debugging" }, 165 | { IFF_LOOPBACK, "Loopback" }, 166 | { IFF_POINTOPOINT, "Ppp" }, 167 | { IFF_NOTRAILERS, "No-trailers" }, 168 | { IFF_RUNNING, "Running" }, 169 | { IFF_NOARP, "No-arp" }, 170 | { IFF_PROMISC, "Promiscuous" }, 171 | { IFF_ALLMULTI, "All-multicast" }, 172 | { IFF_MASTER, "Load-master" }, 173 | { IFF_SLAVE, "Load-slave" }, 174 | { IFF_MULTICAST, "Multicast" }, 175 | { IFF_PORTSEL, "Port-select" }, 176 | { IFF_AUTOMEDIA, "Auto-detect" }, 177 | { IFF_DYNAMIC, "Dynaddr" }, 178 | { 0xffff0000, "Unknown-flags" }, 179 | }; 180 | 181 | if (do_socket_ioctl(iface, SIOCGIFFLAGS, &r, NULL, PRINT_ERROR)) 182 | return; 183 | 184 | for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) 185 | printf("%s%s%s", (r.ifr_flags & flags[i].flag) ? "On " : "Off ", 186 | flags[i].name, 187 | sizeof(flags) / sizeof(flags[0]) - 1 == i ? "" : "\n"); 188 | } 189 | 190 | void if_hwaddr(const char *iface) { 191 | struct ifreq r; 192 | unsigned char *hwaddr; 193 | 194 | if (do_socket_ioctl(iface, SIOCGIFHWADDR, &r, NULL, PRINT_ERROR)) 195 | return; 196 | 197 | hwaddr = (unsigned char *)r.ifr_hwaddr.sa_data; 198 | 199 | if (!hwaddr[0] && !hwaddr[1] && !hwaddr[2] && 200 | !hwaddr[3] && !hwaddr[4] && !hwaddr[5]) { 201 | fprintf(stderr, "Error: %s: no hardware address\n", iface); 202 | exit(1); 203 | } 204 | 205 | printf("%02X:%02X:%02X:%02X:%02X:%02X", 206 | hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); 207 | } 208 | 209 | #endif 210 | 211 | static struct sockaddr *if_addr_value(const char *iface, struct ifreq *r, 212 | unsigned long int request) { 213 | int e; 214 | 215 | if (do_socket_ioctl(iface, request, r, &e, PRINT_NO_ERROR)) { 216 | if (e == EADDRNOTAVAIL) 217 | return &r->ifr_addr; 218 | return NULL; 219 | } 220 | return &r->ifr_addr; 221 | } 222 | 223 | struct sockaddr *if_addr(const char *iface, struct ifreq *r) { 224 | return if_addr_value(iface, r, SIOCGIFADDR); 225 | } 226 | 227 | struct sockaddr *if_mask(const char *iface, struct ifreq *r) { 228 | return if_addr_value(iface, r, SIOCGIFNETMASK); 229 | } 230 | 231 | struct sockaddr *if_bcast(const char *iface, struct ifreq *r) { 232 | return if_addr_value(iface, r, SIOCGIFBRDADDR); 233 | } 234 | 235 | struct sockaddr *if_network(const char *iface) { 236 | struct sockaddr *saddr; 237 | static struct ifreq req; 238 | unsigned int mask; 239 | 240 | if (!(saddr = if_mask(iface, &req))) 241 | return NULL; 242 | 243 | mask = ((struct sockaddr_in*)saddr)->sin_addr.s_addr; 244 | 245 | if (!(saddr = if_addr(iface, &req))) 246 | return NULL; 247 | 248 | ((struct sockaddr_in*)saddr)->sin_addr.s_addr &= mask; 249 | return saddr; 250 | } 251 | 252 | int ifd_if_mtu(const char *iface) { 253 | static struct ifreq req; 254 | 255 | if (do_socket_ioctl(iface, SIOCGIFMTU, &req, NULL, PRINT_ERROR)) 256 | return 0; 257 | 258 | return req.ifr_mtu; 259 | } 260 | 261 | #if defined(__linux__) 262 | 263 | static void skipline(FILE *fd) { 264 | int ch; 265 | do { 266 | ch = getc(fd); 267 | } while (ch != '\n' && ch != EOF); 268 | } 269 | 270 | struct if_stat *get_stats(const char *iface) { 271 | FILE *fd; 272 | struct if_stat *ifstat; 273 | char name[10]; 274 | 275 | if (!(ifstat = malloc(sizeof(struct if_stat)))) { 276 | perror("malloc"); 277 | return NULL; 278 | } 279 | 280 | if ((fd = fopen("/proc/net/dev", "r")) == NULL) { 281 | perror("fopen(\"/proc/net/dev\")"); 282 | free(ifstat); 283 | return NULL; 284 | } 285 | 286 | /* Skip header */ 287 | skipline(fd); 288 | skipline(fd); 289 | 290 | do { 291 | int items = fscanf(fd, 292 | " %20[^:]:%llu %llu %llu %llu %llu %llu %llu %llu " 293 | "%llu %llu %llu %llu %llu %llu %llu %llu", 294 | name, 295 | &ifstat->in_bytes, &ifstat->in_packets, 296 | &ifstat->in_errors, &ifstat->in_drops, 297 | &ifstat->in_fifo, &ifstat->in_frame, 298 | &ifstat->in_compress, &ifstat->in_multicast, 299 | &ifstat->out_bytes, &ifstat->out_packets, 300 | &ifstat->out_errors, &ifstat->out_drops, 301 | &ifstat->out_fifo, &ifstat->out_colls, 302 | &ifstat->out_carrier, &ifstat->out_carrier 303 | ); 304 | 305 | if (items == -1) 306 | break; 307 | if (items != 17) { 308 | fprintf(stderr, "Invalid data read, check!\n"); 309 | break; 310 | } 311 | 312 | if (!strncmp(name, iface, sizeof(name))) { 313 | fclose(fd); 314 | return ifstat; 315 | } 316 | } while (!feof(fd)); 317 | 318 | fclose(fd); 319 | free(ifstat); 320 | return NULL; 321 | } 322 | 323 | #endif 324 | 325 | const struct { 326 | char *option; 327 | unsigned int flag; 328 | unsigned int is_stat; 329 | char *description; 330 | } options[] = { 331 | { "-e", DO_EXISTS, 0, "Reports interface existence via return code" }, 332 | { "-p", DO_PALL, 0, "Print out the whole config of iface" }, 333 | { "-pe", DO_PEXISTS, 0, "Print out yes or no according to existence" }, 334 | { "-pa", DO_PADDRESS, 0, "Print out the address" }, 335 | { "-pn", DO_PMASK, 0, "Print netmask" }, 336 | { "-pN", DO_PNETWORK, 0, "Print network address" }, 337 | { "-pb", DO_PCAST, 0, "Print broadcast" }, 338 | { "-pm", DO_PMTU, 0, "Print mtu" }, 339 | #if defined(__linux__) 340 | { "-ph", DO_PHWADDRESS, 0, "Print out the hardware address" }, 341 | { "-pf", DO_PFLAGS, 0, "Print flags" }, 342 | { "-si", DO_SINALL, 1, "Print all statistics on input" }, 343 | { "-sip", DO_SINPACKETS, 1, "Print # of in packets" }, 344 | { "-sib", DO_SINBYTES, 1, "Print # of in bytes" }, 345 | { "-sie", DO_SINERRORS, 1, "Print # of in errors" }, 346 | { "-sid", DO_SINDROPS, 1, "Print # of in drops" }, 347 | { "-sif", DO_SINFIFO, 1, "Print # of in fifo overruns" }, 348 | { "-sic", DO_SINCOMPRESSES, 1, "Print # of in compress" }, 349 | { "-sim", DO_SINMULTICAST, 1, "Print # of in multicast" }, 350 | { "-so", DO_SOUTALL, 1, "Print all statistics on output" }, 351 | { "-sop", DO_SOUTPACKETS, 1, "Print # of out packets" }, 352 | { "-sob", DO_SOUTBYTES, 1, "Print # of out bytes" }, 353 | { "-soe", DO_SOUTERRORS, 1, "Print # of out errors" }, 354 | { "-sod", DO_SOUTDROPS, 1, "Print # of out drops" }, 355 | { "-sof", DO_SOUTFIFO, 1, "Print # of out fifo overruns" }, 356 | { "-sox", DO_SOUTCOLLS, 1, "Print # of out collisions" }, 357 | { "-soc", DO_SOUTCARRIER, 1, "Print # of out carrier loss" }, 358 | { "-som", DO_SOUTMULTICAST, 1, "Print # of out multicast" }, 359 | { "-bips",DO_BIPS, 1, "Print # of incoming bytes per second" }, 360 | { "-bops",DO_BOPS, 1, "Print # of outgoing bytes per second" }, 361 | #endif 362 | }; 363 | 364 | void usage(const char *name) { 365 | unsigned int i; 366 | 367 | fprintf(stderr, "Usage: %s [options] iface\n", name); 368 | for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) { 369 | fprintf(stderr, " %5s %s\n", 370 | options[i].option, options[i].description); 371 | } 372 | } 373 | 374 | void add_do(int *ndo, int **todo, int act) { 375 | *todo = realloc(*todo, (*ndo+1) * sizeof(int)); 376 | (*todo)[*ndo] = act; 377 | *ndo += 1; 378 | } 379 | 380 | static void print_addr(struct sockaddr *sadr) { 381 | if (!sadr) { 382 | fprintf(stderr, "Error\n"); 383 | exit(1); 384 | } 385 | print_quad(sadr); 386 | } 387 | 388 | struct if_stat *ifstats, *ifstats2 = NULL; 389 | 390 | void please_do(int ndo, int *todo, const char *ifname) { 391 | int i; 392 | int exists; 393 | static struct ifreq req; 394 | if (!ndo) return; 395 | 396 | exists = if_exists(ifname); 397 | 398 | // printf("I have %d items in my queue.\n",ndo); 399 | for (i=0; iin_packets); 447 | break; 448 | case DO_SINBYTES: 449 | printf("%llu",ifstats->in_bytes); 450 | break; 451 | case DO_SINERRORS: 452 | printf("%llu",ifstats->in_errors); 453 | break; 454 | case DO_SINDROPS: 455 | printf("%llu",ifstats->in_drops); 456 | break; 457 | case DO_SINFIFO: 458 | printf("%llu",ifstats->in_fifo); 459 | break; 460 | case DO_SINFRAME: 461 | printf("%llu",ifstats->in_frame); 462 | break; 463 | case DO_SINCOMPRESSES: 464 | printf("%llu",ifstats->in_compress); 465 | break; 466 | case DO_SINMULTICAST: 467 | printf("%llu",ifstats->in_multicast); 468 | break; 469 | case DO_SINALL: 470 | printf("%llu %llu %llu %llu %llu %llu %llu %llu", 471 | ifstats->in_bytes, ifstats->in_packets, 472 | ifstats->in_errors, ifstats->in_drops, 473 | ifstats->in_fifo, ifstats->in_frame, 474 | ifstats->in_compress, ifstats->in_multicast); 475 | break; 476 | case DO_SOUTBYTES: 477 | printf("%llu",ifstats->out_bytes); 478 | break; 479 | case DO_SOUTPACKETS: 480 | printf("%llu",ifstats->out_packets); 481 | break; 482 | case DO_SOUTERRORS: 483 | printf("%llu",ifstats->out_errors); 484 | break; 485 | case DO_SOUTDROPS: 486 | printf("%llu",ifstats->out_drops); 487 | break; 488 | case DO_SOUTFIFO: 489 | printf("%llu",ifstats->out_fifo); 490 | break; 491 | case DO_SOUTCOLLS: 492 | printf("%llu",ifstats->out_colls); 493 | break; 494 | case DO_SOUTCARRIER: 495 | printf("%llu",ifstats->out_carrier); 496 | break; 497 | case DO_SOUTMULTICAST: 498 | printf("%llu",ifstats->out_multicast); 499 | break; 500 | case DO_BIPS: 501 | if (ifstats2 == NULL) { 502 | sleep(1); 503 | ifstats2 = get_stats(ifname); 504 | } 505 | printf("%llu", ifstats2->in_bytes-ifstats->in_bytes); 506 | break; 507 | case DO_BOPS: 508 | if (ifstats2 == NULL) { 509 | sleep(1); 510 | ifstats2 = get_stats(ifname); 511 | } 512 | printf("%llu", ifstats2->out_bytes-ifstats->out_bytes); 513 | break; 514 | case DO_SOUTALL: 515 | printf("%llu %llu %llu %llu %llu %llu %llu %llu", 516 | ifstats->out_bytes, ifstats->out_packets, 517 | ifstats->out_errors, ifstats->out_drops, 518 | ifstats->out_fifo, ifstats->out_colls, 519 | ifstats->out_carrier, ifstats->out_multicast); 520 | break; 521 | #endif 522 | default: 523 | printf("Unknown command: %d", todo[i]); 524 | break; 525 | } 526 | printf("\n"); 527 | } 528 | } 529 | 530 | int main(int argc, char *argv[]) { 531 | int ndo=0; 532 | int *todo=NULL; 533 | char *ifname=NULL; 534 | int narg = 0; 535 | int do_stats = 0; 536 | unsigned int i, found; 537 | 538 | if (argc == 1) { 539 | usage(*argv); 540 | return 1; 541 | } 542 | 543 | while (narg < argc - 1) { 544 | narg++; 545 | 546 | found = 0; 547 | 548 | for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) { 549 | if (!strcmp(argv[narg], options[i].option)) { 550 | add_do(&ndo, &todo, options[i].flag); 551 | do_stats |= options[i].is_stat; 552 | found = 1; 553 | break; 554 | } 555 | } 556 | 557 | if (found) 558 | continue; 559 | 560 | if (argv[narg][0] == '-') { 561 | usage(*argv); 562 | return 1; 563 | } 564 | else { 565 | ifname = argv[narg]; 566 | break; 567 | } 568 | } 569 | 570 | if (narg + 1 < argc || !ifname) { 571 | usage(*argv); 572 | return 1; 573 | } 574 | 575 | #if defined(__linux__) 576 | if (do_stats && (ifstats = get_stats(ifname)) == NULL) { 577 | fprintf(stderr, "Error getting statistics for %s\n", ifname); 578 | return 1; 579 | } 580 | #endif 581 | 582 | please_do(ndo, todo, ifname); 583 | 584 | return 0; 585 | } 586 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | moreutils (0.71) UNRELEASED; urgency=medium 2 | 3 | * ts: Use the last provided switch if both -i and -s are provided 4 | Thanks, Mohammed Sadiq 5 | * Makefile: Fix shell syntax error 6 | Thanks, Nicolas Schier 7 | 8 | -- Joey Hess Mon, 06 Jan 2025 16:39:26 -0400 9 | 10 | moreutils (0.70) unstable; urgency=medium 11 | 12 | * vidir: Improve zero padding to support larger directories, 13 | and also avoid unncessary padding. 14 | Thanks, Martin Kühl 15 | * zrun: Add support for zstd compression 16 | Thanks, Yannick Le Pennec 17 | * ts: Do not accept extra args and always read from stdin (Closes: #1041291) 18 | Thanks, Zefram 19 | 20 | -- Joey Hess Mon, 09 Dec 2024 13:59:48 -0400 21 | 22 | moreutils (0.69) unstable; urgency=medium 23 | 24 | * Makefile: Warn users of pkgx.dev about their poor life choices. 25 | 26 | -- Joey Hess Sun, 25 Feb 2024 15:46:15 -0400 27 | 28 | moreutils (0.68) unstable; urgency=medium 29 | 30 | * popen: Use pclose, fixing compile warning. 31 | Thanks, Mikel Olasagasti Uranga 32 | * vidir: Zero pad line numbers to work better when used with 33 | a small tab size such as 2. 34 | Thanks, Johan Grande 35 | 36 | -- Joey Hess Tue, 28 Nov 2023 14:10:42 -0400 37 | 38 | moreutils (0.67) unstable; urgency=medium 39 | 40 | * README: Formalize that I am not adding new tools to moreutils, 41 | and have not for a long while. This package needs someone new to 42 | take over editorial responsibility. 43 | * Makefile: Install man pages without executable bit. 44 | Thanks, meator 45 | * ifne.1: Improve example that pipes to mail to avoid escape 46 | sequences. 47 | 48 | -- Joey Hess Tue, 21 Dec 2021 15:34:32 -0400 49 | 50 | moreutils (0.66) unstable; urgency=medium 51 | 52 | * vipe: When no output is piped into vipe, and stdin is connected to 53 | the terminal, don't read from stdin before opening the editor. 54 | This allows eg: vipe | command 55 | Thanks, Florian Pensec 56 | * chronic: With -v, flush stdout after printing "STDERR" header. 57 | Thanks, Adam Sjøgren 58 | 59 | -- Joey Hess Thu, 16 Sep 2021 09:12:42 -0400 60 | 61 | moreutils (0.65) unstable; urgency=medium 62 | 63 | * vipe: Added --suffix option. 64 | Thanks, Pål Grønås Drange. 65 | * ifdata: fail when -ph is given but no hwaddr is available 66 | (Closes: #386755) 67 | Thanks, Nicolas Schier 68 | 69 | -- Joey Hess Sat, 02 Jan 2021 12:24:51 -0400 70 | 71 | moreutils (0.64) unstable; urgency=medium 72 | 73 | * parallel: fix typo in usage message. 74 | * Makefile: Propagate compiler and linker flags when building is_utf8. 75 | * ts: Fix parsing of ISO-8601 dates. 76 | Thanks, David Laban. 77 | * parallel: Allow compiling with uClibc-ng, which does not have getloadavg. 78 | Thanks, Rosen Penev 79 | 80 | -- Joey Hess Thu, 20 Aug 2020 13:05:19 -0400 81 | 82 | moreutils (0.63) unstable; urgency=medium 83 | 84 | * vipe: Clean up temp file even when it exits with an error. 85 | Thanks, Stig Palmquist. 86 | * ts: Fix ts -m %.s to not output negative microseconds. 87 | Thanks, Dima Kogan 88 | * sponge: Fix bug in -a mode that doubled original content of file when 89 | the temp file is located on a different filesystem. 90 | 91 | -- Joey Hess Wed, 09 Jan 2019 11:14:01 -0400 92 | 93 | moreutils (0.62) unstable; urgency=medium 94 | 95 | * ts: Add -m option to use monotonic clock. 96 | Thanks, Ben Leinweber 97 | * ts: Added %.T format like %T but with hi-res. 98 | Thanks, Matt Koscica 99 | * pee: Ignore SIGPIPE and write errors caused by the command not 100 | consuming all its input. Closes: #697052 101 | Thanks, Ole Jørgen Brønner 102 | * chronic: document return value semantics of -e option. Closes: #867167 103 | Thanks, Daniel Shahaf 104 | * vidir: reword man page to more explicit mention 'file' args. 105 | Closes: #885221 106 | Thanks, Daniel Shahaf 107 | * pee: Don't buffer input, bringing behavior into line with tee. 108 | Thanks, Sauerbeck Tilman 109 | 110 | -- Joey Hess Sun, 31 Dec 2017 12:02:05 -0400 111 | 112 | moreutils (0.61) unstable; urgency=medium 113 | 114 | * chronic: Flush output more often to better preserve stdout,err ordering. 115 | Thanks, Miroslav Šustek 116 | 117 | -- Joey Hess Wed, 19 Apr 2017 10:23:11 -0400 118 | 119 | moreutils (0.60) unstable; urgency=medium 120 | 121 | * New implementation of isutf8 by Julien Palard. 122 | - Noncharacters (ending with 0xFFFF and 0xFFFE) were considered 123 | invalid when encoded in utf8, according to the unicode standard 124 | they are valid: "However, they are not illegal in interchange, nor 125 | does their presence cause Unicode text to be ill-formed." 126 | - \xf4\xbf\xbf\xbf was considered valid UTF8, which is not: after 127 | 0xF4 the following byte should be between 80 and 8F. 128 | - This implementation does not try to decode the stream, so it checks 129 | it faster. 130 | - Add --list option. Closes: #691330 131 | * Support bullding in Cygwin. 132 | Thanks, StalkR 133 | * OSX build fix. 134 | Thanks, Tony Kelman. 135 | 136 | -- Joey Hess Fri, 12 Aug 2016 19:15:57 -0400 137 | 138 | moreutils (0.59) unstable; urgency=medium 139 | 140 | * Makefile: add DOCBOOKXSL setting. 141 | Thanks, Kevin Bullock 142 | * parallel: include signal.h to fix warning when building with clang 143 | Thanks, Kevin Bullock 144 | * chronic: Added -v option for more verbose output. 145 | Thanks, Tomas Mudrunka 146 | * chronic: Added -e option to display any stderr. 147 | Thanks, Tomas Mudrunka 148 | 149 | -- Joey Hess Sat, 02 Apr 2016 15:23:08 -0400 150 | 151 | moreutils (0.58) unstable; urgency=medium 152 | 153 | * OpenBSD compile fix. 154 | Thanks, Michael Reed. 155 | * ts: Quiet perl's complaints about utf-8. Closes: #812143 156 | Thanks, Nicolas Schier. 157 | 158 | -- Joey Hess Tue, 23 Feb 2016 17:11:52 -0400 159 | 160 | moreutils (0.57) unstable; urgency=medium 161 | 162 | * Avoid using non-portable error() in ifdata, a portability reversion 163 | introduced in 0.56. 164 | 165 | -- Joey Hess Mon, 13 Jul 2015 18:29:06 -0400 166 | 167 | moreutils (0.56) unstable; urgency=medium 168 | 169 | * ifdata: Fix error messages when a non-existent network interface 170 | is queried. Closes: #386754 Thanks, Nicolas Schier 171 | * errno.docbook: Fix typo. Closes: #749399 172 | * vidir: Create missing target directories. Closes: #728688 173 | Thanks, Nicolas Schier 174 | 175 | -- Joey Hess Wed, 03 Jun 2015 12:03:50 -0400 176 | 177 | moreutils (0.55) unstable; urgency=medium 178 | 179 | * parallel: serialise output through internal pipe. Closes: #704125 180 | Thanks, Nicolas Schier. 181 | * sponge: add append option '-a'. Closes: #623197 182 | Thanks, Nicolas Schier. 183 | 184 | -- Joey Hess Mon, 19 Jan 2015 13:58:08 -0400 185 | 186 | moreutils (0.54) unstable; urgency=medium 187 | 188 | * vidir: Fix bug in handling filenames that share a common 189 | prefix when renaming. Closes: #654326 190 | Thanks, Kushal Kumaran 191 | 192 | -- Joey Hess Fri, 28 Nov 2014 11:25:32 -0400 193 | 194 | moreutils (0.53) unstable; urgency=medium 195 | 196 | * Orphaned the Debian package. 197 | 198 | -- Joey Hess Sat, 08 Nov 2014 00:31:54 -0400 199 | 200 | moreutils (0.52) unstable; urgency=medium 201 | 202 | * Fix docbook markup for parallel examples. Closes: #756377 203 | * ts: Add -s option to make timestamp relative to start. 204 | Thanks, Adam Juraszek. 205 | 206 | -- Joey Hess Tue, 09 Sep 2014 14:12:05 -0400 207 | 208 | moreutils (0.51) unstable; urgency=low 209 | 210 | * Fix ifdata to build on OS X. Thanks, Peter Eisentraut 211 | Closes: #575294 212 | * use docbook-xsl for building man pages. Thanks, Peter Eisentraut 213 | for extensive patch set! 214 | Closes: #728831 215 | * Fix ifdata, ifne, parallel to build on illumos. Thanks, Gabriele Giacone 216 | Closes: #733736 217 | 218 | -- Joey Hess Thu, 27 Feb 2014 12:01:21 -0400 219 | 220 | moreutils (0.50) unstable; urgency=low 221 | 222 | * Fix build on Hurd. Closes: #716653 223 | (Thanks, Pino Toscano) 224 | 225 | -- Joey Hess Mon, 26 Aug 2013 13:00:24 -0400 226 | 227 | moreutils (0.49) unstable; urgency=low 228 | 229 | * ts: Fix timezone used with -i 230 | * errno, isutf8: Fix zero-termination of option list, which could lead 231 | to getopt crash. Closes: #715867 232 | (Thanks, Mayhem Team) 233 | 234 | -- Joey Hess Wed, 10 Jul 2013 16:21:41 -0400 235 | 236 | moreutils (0.48) unstable; urgency=low 237 | 238 | * Allow overriding PREFIX and CFLAGS to make the build more flexible 239 | (Thanks, Ben Walton) 240 | * Typo. Closes: #697113 241 | * ts: -i enables incremental timestamping. 242 | Thanks, Thomas Vander Stichele 243 | * ts: Support single-digit day dates. 244 | Thanks, Peter Lunicks 245 | * sponge: Check fclose to detect certian short reads. Closes: #704453 246 | 247 | -- Joey Hess Sat, 04 May 2013 23:50:03 -0400 248 | 249 | moreutils (0.47) unstable; urgency=low 250 | 251 | * errno: New utility that looks up errno numbers or names. 252 | 253 | -- Joey Hess Mon, 25 Jun 2012 16:31:17 -0400 254 | 255 | moreutils (0.46) unstable; urgency=low 256 | 257 | * Typo. Closes: #649158 258 | * combine: Avoid reading files twice, to support data coming from 259 | pipes. Closes: #667960 Thanks, Carsten Hey 260 | 261 | -- Joey Hess Mon, 09 Apr 2012 16:19:34 -0400 262 | 263 | moreutils (0.45) unstable; urgency=low 264 | 265 | * ts: Support %.s for seconds sinch epoch with subsecond resolution. 266 | Closes: #619764 267 | 268 | -- Joey Hess Sun, 19 Jun 2011 15:44:28 -0400 269 | 270 | moreutils (0.44) unstable; urgency=low 271 | 272 | * pee: Propigate exit status of commands run. 273 | 274 | -- Joey Hess Thu, 10 Mar 2011 17:38:14 -0400 275 | 276 | moreutils (0.43) unstable; urgency=low 277 | 278 | * chronic: New command, runs a command quietly, unless it fails. 279 | * Now depends on IPC::Run, used by chronic. 280 | 281 | -- Joey Hess Fri, 29 Oct 2010 15:54:37 -0400 282 | 283 | moreutils (0.42) unstable; urgency=low 284 | 285 | * sponge: Guarantee that output file is always updated atomically, 286 | by renaming a temp file into place. Closes: #592144 287 | * sponge: Ensure that output file permissions are always preserved 288 | if it already exists. 289 | * Typo. Closes: #596032 290 | 291 | -- Joey Hess Wed, 06 Oct 2010 20:03:25 -0400 292 | 293 | moreutils (0.41) unstable; urgency=low 294 | 295 | * ifdata.docbook: Mark interface as required in synopsis. Closes: #588397 296 | * Add missing AUTHOR section to docbook man pages. 297 | * sponge: Correct bad use of fread that caused a trailing quantity of 298 | soaked data to be silently discarded when a temp file was used 299 | and sponge output to stdout. Closes: #595220 300 | 301 | -- Joey Hess Thu, 02 Sep 2010 16:47:10 -0400 302 | 303 | moreutils (0.40) unstable; urgency=low 304 | 305 | * lckdo: Now deprecated, since util-linux's flock(1) can do the same 306 | thing. 307 | * parallel: -i will now replace {} inside parameters, before the {} had 308 | to be a separate parameter. 309 | 310 | -- Joey Hess Tue, 06 Jul 2010 19:38:14 -0400 311 | 312 | moreutils (0.39) unstable; urgency=low 313 | 314 | * parallel: Fix exit code handling when commands are specified after -- 315 | * parallel: Make -j 0 do something reasonable (start all jobs at once). 316 | * parallel: Fix to really avoid running new jobs when load is too high. 317 | * parallel: Fix logic error in code handling -l that could make parallel 318 | return a bogus 255 exit code when all jobs succeeded. Closes: #569617 319 | * parallel: Allow a decimal load value to be specified with -l 320 | * Caps sillyness. Closes: #570815 321 | * zrun: Add support for .xz files. 322 | 323 | -- Joey Hess Tue, 23 Feb 2010 15:51:26 -0500 324 | 325 | moreutils (0.38) unstable; urgency=low 326 | 327 | * Description improvements. Closes: #549450 328 | (Thanks, Justin B Rye) 329 | * parallel: Allow running independent commands, 330 | like `parallel -j3 -- ls df "echo hi"` 331 | * ifdata: Add FreeBSD kernel support, although some of the more esoteric 332 | interface options are not currently supported in FreeBSD. 333 | * parallel: Define WEXITED to allow building on FreeBSD kernel. 334 | * Thanks Enrico Tassi for the FreeBSD kernel support, which should 335 | be enough to get moreutils built on Debian kFreeBSD. Closes: #562609 336 | 337 | -- Joey Hess Tue, 09 Feb 2010 15:50:42 -0500 338 | 339 | moreutils (0.37) unstable; urgency=low 340 | 341 | * parallel: Clarify man page regarding CPUs. Closes: #536597 342 | * parallel: Add -n option. Thanks, Pierre Habouzit. Closes: #537992 343 | (As a side effect, fixes a segfault if -- was omitted.) 344 | * parallel.1: Typo fixes. Closes: #538147 345 | 346 | -- Joey Hess Sat, 25 Jul 2009 10:18:40 +0200 347 | 348 | moreutils (0.36) unstable; urgency=low 349 | 350 | * parallel: New program, contributed by Tollef Fog Heen, 351 | that can run multiple jobs in parallel, optionally checking 352 | load average. 353 | * mispipe: Fix closing of extra pipe FD before starting command 354 | so it is not inherited by daemons. Closes: #533448 355 | (Thanks, Jeremie Koenig) 356 | 357 | -- Joey Hess Fri, 10 Jul 2009 11:01:41 -0400 358 | 359 | moreutils (0.35) unstable; urgency=low 360 | 361 | * ifdata: Don't assume that all interface names are 6 characters or less, 362 | for instance "wmaster0" is longer. Increase the limit to 20 characters. 363 | Closes: #526654 (Thanks, Alan Pope) 364 | * isutf8: Reject UTF-8-encoded UTF-16 surrogates. Closes: #525301 365 | (Thanks, Jakub Wilk and liw) 366 | 367 | -- Joey Hess Tue, 05 May 2009 15:06:41 -0400 368 | 369 | moreutils (0.34) unstable; urgency=low 370 | 371 | * vipe: Avoid dying on empty input. Thanks, Anders Kaseorg 372 | Closes: #508491 373 | 374 | -- Joey Hess Thu, 11 Dec 2008 15:11:23 -0500 375 | 376 | moreutils (0.33) unstable; urgency=low 377 | 378 | * Support installing moreutils into prefixes other than /usr (Evan Broder) 379 | * Fix zrun breakage introduced last version. Closes: #504129 380 | 381 | -- Joey Hess Fri, 31 Oct 2008 17:01:03 -0400 382 | 383 | moreutils (0.32) unstable; urgency=low 384 | 385 | * zrun: Can be linked to zsomeprog to run the equivilant of zrun someprog. 386 | Closes: #411623 (Stefan Fritsch) 387 | * zrun: Add support for lzma and lzo. (Stefan Fritsch) 388 | * Fix pod error in vidir(1). 389 | 390 | -- Joey Hess Sun, 26 Oct 2008 23:43:30 -0400 391 | 392 | moreutils (0.31) unstable; urgency=low 393 | 394 | * pee.1: Document difference with tee in stdout. 395 | * ts: Support displaying fractional seconds via a "%.S" conversion 396 | specification. Closes: #482789 397 | 398 | -- Joey Hess Sat, 28 Jun 2008 23:19:31 -0400 399 | 400 | moreutils (0.30) unstable; urgency=low 401 | 402 | * debhelper v7; rules file minimisation 403 | * Use DESTDIR instead of PREFIX. 404 | * Add a DOCBOOK2XMAN setting. (Greg KH) 405 | * ifne: Add -n which makes it run the command if stdin is empty. 406 | * ifne: If no command is specified, print usage information. 407 | 408 | -- Joey Hess Wed, 14 May 2008 19:37:42 -0400 409 | 410 | moreutils (0.29) unstable; urgency=low 411 | 412 | * Add ifne, contributed by Javier Merino. 413 | * sponge, ifne: Ensure that suspending/resuming doesn't 414 | result in partial writes of the data, by using fwrite() 415 | rather than write(). 416 | * sponge: Handle large data sizes by using a temp file rather than by 417 | consuming arbitrary amounts of memory. Patch by Brock Noland. 418 | * ts: Allow both -r and a format to be specified, to parse dates and output 419 | in a specified format. 420 | * ts: Fix bug in timezone regexp. 421 | 422 | -- Joey Hess Tue, 15 Apr 2008 15:30:52 -0400 423 | 424 | moreutils (0.28) unstable; urgency=low 425 | 426 | * Moved to a git repository. 427 | * vidir: Applied patch from Stefan Fritsch (one part of #412176): 428 | - Check for control characters (especially newlines) in filenames 429 | and error out, since this can greatly confuse the editor or vidir. 430 | - If the source of a rename does not exist (and thus the rename will fail 431 | anyway), vidir should not move an existing target file to a tmpfile. 432 | - If a directory is renamed, vidir should take that into account when 433 | renaming files in this directory. 434 | - If a directory name is passed as name/ to vidir, vidir should not 435 | add second slash after the name. 436 | * vidir: Add support for unlinking directories. To recursivly delete 437 | a directory and its contents, pipe find to vidir, and delete the directory 438 | and its contents in the editor. Closes: #412176 439 | * Add example to man page about recursive modification of directories. 440 | Closes: #390099 441 | 442 | -- Joey Hess Sat, 02 Feb 2008 17:26:23 -0500 443 | 444 | moreutils (0.27) unstable; urgency=low 445 | 446 | * vidir: Check exit codes of close. Closes: #463739 447 | 448 | -- Joey Hess Sat, 02 Feb 2008 16:42:18 -0500 449 | 450 | moreutils (0.26) unstable; urgency=low 451 | 452 | * isutf8: Correct inverted exit code when passed a file to check. 453 | Closes: #453306 454 | 455 | -- Joey Hess Wed, 28 Nov 2007 14:19:32 -0500 456 | 457 | moreutils (0.25) unstable; urgency=low 458 | 459 | * isutf8: Detect and reject overlong UTF-8 sequences. Closes: #440951 460 | Many thanks to liw for the patch. 461 | 462 | -- Joey Hess Mon, 12 Nov 2007 11:58:07 -0500 463 | 464 | moreutils (0.24) unstable; urgency=low 465 | 466 | * vidir: Force numbers to normalised integers. 467 | * vidir: Abort on unknown item numbers rather than deleting them. 468 | Closes: #442440 469 | 470 | -- Joey Hess Sun, 16 Sep 2007 13:05:54 -0400 471 | 472 | moreutils (0.23) unstable; urgency=low 473 | 474 | * Add pointer to join from combine's man page. Closes: #435516 475 | * Don't strip binaries for debian package if built with 476 | DEB_BUILD_OPTIONS=nostrip. Closes: #437577 477 | * Include Michael Tokarev's lckdo program and replace / conflict with the 478 | current lckdo package. (Robert Edmonds) Closes: #432906 479 | * lckdo: Don't clear other flags when setting close on exec. 480 | 481 | -- Joey Hess Wed, 05 Sep 2007 21:45:25 -0400 482 | 483 | moreutils (0.22) unstable; urgency=low 484 | 485 | * vidir, zrun: Don't put temp files in the current directory. Closes: #429367 486 | 487 | -- Joey Hess Mon, 25 Jun 2007 16:11:27 -0400 488 | 489 | moreutils (0.21) unstable; urgency=low 490 | 491 | * Patch from Sergej Pupykin fixing ifdata -pN. 492 | 493 | -- Joey Hess Mon, 25 Jun 2007 13:07:21 -0400 494 | 495 | moreutils (0.20) unstable; urgency=low 496 | 497 | * Typo fixes from Ralf Wildenhues. 498 | * ifdata: Add -bips and -bops options contributed by André Appel, 499 | to print the number of bytes of incoming/outgoing traffic per second. 500 | 501 | -- Joey Hess Sat, 23 Dec 2006 15:55:45 -0500 502 | 503 | moreutils (0.19) unstable; urgency=low 504 | 505 | * vidir: Don't ignore files whose names end in dots. Closes: #398141 506 | Thanks, Bram Sanders. 507 | 508 | -- Joey Hess Sat, 11 Nov 2006 22:02:17 -0500 509 | 510 | moreutils (0.18) unstable; urgency=low 511 | 512 | * mispipe.docbook: Typo. Closes: #386756 513 | * spongs: Output to stdout if no file is specified, useful in a pipeline 514 | such as: cvs diff | sponge | patch -R -p0 515 | Closes: #387501 516 | 517 | -- Joey Hess Thu, 14 Sep 2006 15:13:46 -0400 518 | 519 | moreutils (0.17) unstable; urgency=low 520 | 521 | * Add missing \n to sponge usage. Closes: #383944 522 | * Add mispipe, contributed by Nathanael Nerode. Pipes together two commands, 523 | returning the exit status of the first. 524 | 525 | -- Joey Hess Thu, 7 Sep 2006 20:49:16 -0400 526 | 527 | moreutils (0.16) unstable; urgency=low 528 | 529 | * Change the default ts format to include the month and day, for consistency 530 | with syslog format. 531 | * Add -r switch to ts, which makes it convert existing timestamps in 532 | the input into relative times, such as "15m2s ago". Many common date 533 | formats are supported. 534 | 535 | -- Joey Hess Sat, 19 Aug 2006 15:27:42 -0400 536 | 537 | moreutils (0.15) unstable; urgency=low 538 | 539 | * Remove notes about potential tools from README, moved to wiki. 540 | * vidir: Don't abort if it sees an empty or all-whitespace line. 541 | * vidir: If just a filename is removed and the number is left, 542 | treat this the same as removing the whole line, and delete the file, 543 | instead of trying to rename the file to "". 544 | * vidir: Remove the periods after the item numbers. 545 | * vidir: Man page improvements. Closes: #378122 546 | * combine: Man page improvements, to clarify even more that order does 547 | matter and that the operations are not commutative. Closes: #361123 548 | * combine: The behavior of "or" was fairly strange if lines were repeated in 549 | a file. Changed behavior to just print all lines from both files, even 550 | if this means printing dups. Not sure I like this behavior either, but 551 | it's consistent with the very useful behaviors of "and" and "not". 552 | * vidir, vipe: Use /usr/bin/editor if it's present, and EDITOR and VISUAL 553 | arn't set, to comply with Debian policy. For portability, fall back to vi 554 | if there's no /usr/bin/editor. Closes: #378623 555 | 556 | -- Joey Hess Tue, 25 Jul 2006 22:26:56 -0400 557 | 558 | moreutils (0.14) unstable; urgency=low 559 | 560 | * vidir: Also support EDITOR or VISUAL that contains spaces and parameters. 561 | 562 | -- Joey Hess Wed, 12 Jul 2006 13:35:49 -0400 563 | 564 | moreutils (0.13) unstable; urgency=low 565 | 566 | * ifdata: typo 567 | * vipe: Support EDITOR or VISUAL that contains spaces and parameters. 568 | 569 | -- Joey Hess Wed, 12 Jul 2006 12:53:44 -0400 570 | 571 | moreutils (0.12) unstable; urgency=low 572 | 573 | * Really fix typo. Closes: #369485 574 | * zrun: Add usage message. 575 | * ifdata: Fix bug in argument parsing that could make it segfault. 576 | * combine: Allow operators to be written in any case. 577 | 578 | -- Joey Hess Wed, 28 Jun 2006 14:04:49 -0400 579 | 580 | moreutils (0.11) unstable; urgency=low 581 | 582 | * combine: better synopsis. Closes: #360544 583 | * ifdata: basically rewritten by Adam Lackorzynski, code size is 40% 584 | smaller, macros removed, return checks added for all lib calls. 585 | Closes: #361728 586 | * vidir: behave properly if passed a directory name to edit. Closes: #369156 587 | * check-isutf8: needs to be a bash script, the way it encodes characters 588 | won't work with dash. 589 | * check-isutf8: exit nonzero if any tests fail 590 | 591 | -- Joey Hess Sat, 27 May 2006 19:12:50 -0400 592 | 593 | moreutils (0.10) unstable; urgency=low 594 | 595 | * ifdata: patch from Adam Lackorzynski to translate French error messages 596 | to English and to convert some #defines to enums. 597 | * ifdata: patch from Adam Lackorzynski to avoid printing info for 598 | bogus interface. Closes: #360433 599 | * Add zrun, contributed by Chung-chieh Shan (you might prefer to alias it to 600 | "z"). 601 | 602 | -- Joey Hess Sun, 2 Apr 2006 18:34:01 -0400 603 | 604 | moreutils (0.9) unstable; urgency=low 605 | 606 | * ifdata: robustness patch from Adam Lackorzynski, in particular deal with 607 | /proc not mounted. Closes: #358930 608 | * Typo fixes. Closes: #359039, #359040 609 | * pee: don't send a copy of every line sent to every command to stdout. 610 | Seems best for it not to output anything to stdout on its on at all. 611 | Closes: #359041 612 | 613 | -- Joey Hess Mon, 27 Mar 2006 13:45:45 -0500 614 | 615 | moreutils (0.8) unstable; urgency=low 616 | 617 | * Back to Mithandir's C sponge, now fixed. 618 | * tss.1, ifdata.1: typo fix. Closes: #358557, #358556 619 | * ifdata: patch from its author to make it behave properly on big endian 620 | systems. Closes: #358860 621 | 622 | -- Joey Hess Fri, 24 Mar 2006 20:52:21 -0500 623 | 624 | moreutils (0.7) unstable; urgency=low 625 | 626 | * Add pee (pipe tee) contributed by Miek Gieben. 627 | * ifdata: Patch from KELEMEN Peter to add support for printing hardware 628 | interface. Closes: #357646 629 | 630 | -- Joey Hess Sat, 18 Mar 2006 14:17:08 -0500 631 | 632 | moreutils (0.6) unstable; urgency=low 633 | 634 | * Revert to perl sponge since the C one corrupts larger files. 635 | Hopefully temporary.. 636 | 637 | -- Joey Hess Fri, 10 Mar 2006 15:33:43 -0500 638 | 639 | moreutils (0.5) unstable; urgency=low 640 | 641 | * Added ifdata, by Benjamin BAYART (originally called ifcfg). 642 | * Made ifdata -Wall clean. 643 | * Made ifdata support -h and print usage on unknown options. 644 | * Cleaned up ifdata's behavior when asked to print info for nonexistant 645 | devices. Still needs improvement. 646 | * Indentation improvements. 647 | * Replaced and(1) and not(1) by combine, based on an idea by Matt Taggart. 648 | 649 | -- Joey Hess Tue, 7 Mar 2006 23:02:14 -0500 650 | 651 | moreutils (0.4) unstable; urgency=low 652 | 653 | * Added versions of and(1) and not(1) that support arbitrary numbers of 654 | input files. 655 | 656 | -- Joey Hess Sun, 5 Mar 2006 22:28:13 -0500 657 | 658 | moreutils (0.3) unstable; urgency=low 659 | 660 | * Switch sponge to a C implementation by mithandir. 661 | * Added a list of prospective tools that I am considering adding to the 662 | README file. 663 | 664 | -- Joey Hess Fri, 3 Mar 2006 18:09:46 -0500 665 | 666 | moreutils (0.2) unstable; urgency=low 667 | 668 | * Build dep on docbook-xml. 669 | 670 | -- Joey Hess Sun, 19 Feb 2006 18:40:56 -0500 671 | 672 | moreutils (0.1) unstable; urgency=low 673 | 674 | * First release. 675 | 676 | -- Joey Hess Sun, 12 Feb 2006 17:11:21 -0500 677 | --------------------------------------------------------------------------------