Merge commit 'upstream/1.4'
[debian/gzip] / zgrep.in
1 #!/bin/sh
2
3 # zgrep -- a wrapper around a grep program that decompresses files as needed
4 # Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca>
5
6 # Copyright (C) 1998, 2001, 2002, 2006, 2007, 2009 Free Software Foundation
7 # Copyright (C) 1993 Jean-loup Gailly
8
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
13
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18
19 # You should have received a copy of the GNU General Public License along
20 # with this program; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 bindir=@bindir@
24 case $1 in
25 --__bindir) bindir=${2?}; shift; shift;;
26 esac
27 PATH=$bindir:$PATH
28
29 grep='${GREP-grep}'
30
31 version='zgrep (gzip) @VERSION@
32 Copyright (C) 2007, 2009-2010 Free Software Foundation, Inc.
33 This is free software.  You may redistribute copies of it under the terms of
34 the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
35 There is NO WARRANTY, to the extent permitted by law.
36
37 Written by Jean-loup Gailly.'
38
39 usage="Usage: $0 [OPTION]... [-e] PATTERN [FILE]...
40 Look for instances of PATTERN in the input FILEs, using their
41 uncompressed contents if they are compressed.
42
43 OPTIONs are the same as for 'grep'.
44
45 Report bugs to <bug-gzip@gnu.org>."
46
47 # sed script to escape all ' for the shell, and then (to handle trailing
48 # newlines correctly) turn trailing X on last line into '.
49 escape='
50   s/'\''/'\''\\'\'''\''/g
51   $s/X$/'\''/
52 '
53 operands=
54 have_pat=0
55 pat_on_stdin=0
56 files_with_matches=0
57 files_without_matches=0
58 no_filename=0
59 with_filename=0
60
61 while test $# -ne 0; do
62   option=$1
63   shift
64   optarg=
65
66   case $option in
67   (-[0123456789abcdhHiIKLlnoqrRsTuUvVwxyzZ]?*)
68     arg2=-\'$(expr "X${option}X" : 'X-.[0-9]*\(.*\)' | sed "$escape")
69     eval "set -- $arg2 "'${1+"$@"}'
70     option=$(expr "X$option" : 'X\(-.[0-9]*\)');;
71   (--binary-*=* | --[lm]a*=* | --reg*=*)
72     ;;
73   (-[ABCDefm] | --binary-* | --file | --[lm]a* | --reg*)
74     case ${1?"$option option requires an argument"} in
75     (*\'*)
76       optarg=" '"$(printf '%sX\n' "$1" | sed "$escape");;
77     (*)
78       optarg=" '$1'";;
79     esac
80     shift;;
81   (--)
82     break;;
83   (-?*)
84     ;;
85   (*)
86     case $option in
87     (*\'*)
88       operands="$operands '"$(printf '%sX\n' "$option" | sed "$escape");;
89     (*)
90       operands="$operands '$option'";;
91     esac
92     ${POSIXLY_CORRECT+break}
93     continue;;
94   esac
95
96   case $option in
97   (-[drRzZ] | --di* | --exc* | --inc* | --rec* | --nu*)
98     printf >&2 '%s: %s: option not supported\n' "$0" "$option"
99     exit 2;;
100   (-[ef]* | --file | --file=* | --reg*)
101     # The pattern is coming from a file rather than the command-line.
102     # If the file is actually stdin then we need to do a little
103     # magic, (since we use stdin to pass the gzip output to grep).
104     # So find a free fd and change the argument to then use this
105     # file descriptor for the pattern.
106     case $optarg in
107     (" '-'" | " '/dev/stdin'" | " '/dev/fd/0'")
108       pat_on_stdin=1
109       eval 'test -e .' 2>/dev/null \
110         && eval 'exists(){ test -e "$@"; }' \
111         || eval 'exists(){ test -r "$@" || test -w "$@"; }'
112       # Start search from 6 since the script already uses 3 and 5
113       fd=6
114       pat_fd=
115       while : ; do
116         if ! exists /proc/$$/fd/$fd; then
117           pat_fd=$fd
118           break;
119         fi
120         fd=$(expr $fd + 1)
121         if test $fd = 255; then
122           printf >&2 '%s: no free file descriptor\n' "$0"
123           exit 2
124         fi
125       done
126       optarg=/dev/fd/$pat_fd;
127     esac
128     have_pat=1;;
129   (--h | --he | --hel | --help)
130     echo "$usage" || exit 2
131     exit;;
132   (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \
133   | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \
134   | --with-filename)
135     with_filename=1
136     continue;;
137   (-l | --files-with-*)
138     files_with_matches=1;;
139   (-L | --files-witho*)
140     files_without_matches=1;;
141   (--no-f*)
142     no_filename=1;;
143   (-V | --v | --ve | --ver | --vers | --versi | --versio | --version)
144     echo "$version" || exit 2
145     exit;;
146   esac
147
148   case $option in
149   (*\'?*)
150     option=\'$(expr "X${option}X" : 'X\(.*\)' | sed "$escape");;
151   (*)
152     option="'$option'";;
153   esac
154
155   grep="$grep $option$optarg"
156 done
157
158 eval "set -- $operands "'${1+"$@"}'
159
160 if test $have_pat -eq 0; then
161   case ${1?"missing pattern; try \`$0 --help' for help"} in
162   (*\'*)
163     grep="$grep -- '"$(printf '%sX\n' "$1" | sed "$escape");;
164   (*)
165     grep="$grep -- '$1'";;
166   esac
167   shift
168 fi
169
170 if test $# -eq 0; then
171   set -- -
172 fi
173
174 exec 3>&1
175 res=0
176
177 for i
178 do
179   # Fail if gzip or grep (or sed) fails.
180   gzip_status=$(
181     exec 5>&1
182     if test $pat_on_stdin -eq 1; then
183       eval "exec $pat_fd<&0"
184     fi
185     (gzip -cdfq -- "$i" 5>&-; echo $? >&5) 3>&- |
186     if test $files_with_matches -eq 1; then
187       eval "$grep" >/dev/null && { printf '%s\n' "$i" || exit 2; }
188     elif test $files_without_matches -eq 1; then
189       eval "$grep" >/dev/null || {
190         r=$?
191         if test $r -eq 1; then
192           printf '%s\n' "$i" || r=2
193         fi
194         exit $r
195       }
196     elif test $with_filename -eq 0 &&
197          { test $# -eq 1 || test $no_filename -eq 1; }; then
198       eval "$grep"
199     else
200       case $i in
201       (*'
202 '* | *'&'* | *'\'* | *'|'*)
203         i=$(printf '%s\n' "$i" |
204             sed '
205               $!N
206               $s/[&\|]/\\&/g
207               $s/\n/\\n/g
208             ');;
209       esac
210       sed_script="s|^|$i:|"
211
212       # Fail if grep or sed fails.
213       r=$(
214         exec 4>&1
215         (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&-
216       ) || r=2
217       exit $r
218     fi >&3 5>&-
219   )
220   r=$?
221   test "$gzip_status" -eq 0 || test "$gzip_status" -eq 2 || r=2
222   test $res -lt $r && res=$r
223 done
224 exit $res