1 /* $NetBSD: util.c,v 1.5 2007/12/06 20:33:49 cjep Exp $ */
4 * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: util.c,v 1.5 2007/12/06 20:33:49 cjep Exp $");
35 #include <sys/types.h>
52 * Process a file line by line...
55 static int linesqueued
, newfile
;
56 static int procline(str_t
*l
, int nottext
);
59 grep_tree(char **argv
)
67 /* if (linkbehave == LINK_EXPLICIT)
68 fts_flags = FTS_COMFOLLOW;
69 if (linkbehave == LINK_SKIP)
70 fts_flags = FTS_PHYSICAL;
71 if (linkbehave == LINK_FOLLOW)
72 fts_flags = FTS_LOGICAL;*/
74 fts_flags
|= FTS_NOSTAT
| FTS_NOCHDIR
| FTS_LOGICAL
;
76 if ((fts
= fts_open(argv
, fts_flags
, NULL
)) == NULL
)
78 while ((p
= fts_read(fts
)) != NULL
) {
79 switch (p
->fts_info
) {
83 errx(2, "%s: %s", p
->fts_path
, strerror(p
->fts_errno
));
89 warnx("warning: %s: recursive directory loop",
93 c
+= procfile(p
->fts_path
);
102 procfile(const char *fn
)
108 int c
, t
, z
, nottext
, skip
;
115 f
= grep_fdopen(STDIN_FILENO
, "r");
118 if (dirbehave
== GREP_SKIP
|| devbehave
== GREP_SKIP
) {
120 fprintf(stderr
, "Cannot stat %s %d\n",
122 /* XXX record error variable */
124 s
= sb
.st_mode
& S_IFMT
;
125 if (s
== S_IFDIR
&& dirbehave
== GREP_SKIP
)
127 if ( (s
== S_IFIFO
|| s
== S_IFCHR
||
128 s
== S_IFBLK
|| s
== S_IFSOCK
)
129 && devbehave
== GREP_SKIP
)
136 f
= grep_open(fn
, "r");
144 nottext
= grep_bin_file(f
);
146 if (nottext
&& binbehave
== BIN_FILE_SKIP
) {
147 /* Skip this file as it is binary */
159 for (c
= 0; !(lflag
&& c
);) {
160 ln
.off
+= ln
.len
+ 1;
161 if ((ln
.dat
= grep_fgetln(f
, &ln
.len
)) == NULL
)
163 if (ln
.len
> 0 && ln
.dat
[ln
.len
- 1] == line_endchar
)
169 if ((t
= procline(&ln
, nottext
)) == 0 && Bflag
> 0 && z
== 0) {
175 /* If we have a maximum number of matches, stop processing */
176 if (mflag
&& c
>= maxcount
)
184 if (output_filenames
)
185 printf("%s%c", ln
.file
, fn_colonchar
);
190 printf("%s%c", fn
, fn_endchar
);
192 printf("%s%c", fn
, fn_endchar
);
193 if (c
&& !cflag
&& !lflag
&& !Lflag
&&
194 binbehave
== BIN_FILE_BIN
&& nottext
&& !qflag
)
195 printf("Binary file %s matches\n", fn
);
202 * Process an individual line in a file. Return non-zero if it matches.
205 #define isword(x) (isalnum((unsigned char)(x)) || (x) == '_')
208 procline(str_t
*l
, int nottext
)
211 regmatch_t matches
[MAX_LINE_MATCHES
];
212 int c
= 0, i
, r
, t
, m
= 0;
220 t
= vflag
? REG_NOMATCH
: 0;
222 while (st
>= 0 && (size_t)st
<= l
->len
) {
224 pmatch
.rm_eo
= l
->len
;
225 for (i
= 0; i
< patterns
; i
++) {
226 r
= regexec(&r_pattern
[i
], l
->dat
, 1, &pmatch
, eflags
);
227 if (r
== REG_NOMATCH
&& t
== 0)
231 if ((pmatch
.rm_so
!= 0 && isword((unsigned char)l
->dat
[pmatch
.rm_so
- 1]))
232 || ((size_t)pmatch
.rm_eo
!= l
->len
&& isword((unsigned char)l
->dat
[pmatch
.rm_eo
])))
236 if (pmatch
.rm_so
!= 0 || (size_t)pmatch
.rm_eo
!= l
->len
)
243 if (m
< MAX_LINE_MATCHES
) {
252 /* One pass if we are not recording matches */
253 if (!oflag
&& !colours
)
256 if (st
== pmatch
.rm_so
)
257 break; /* No matches */
263 if (c
&& binbehave
== BIN_FILE_BIN
&& nottext
)
264 return c
; /* Binary file */
266 if ((tail
> 0 || c
) && !cflag
&& !qflag
) {
269 if ( (Aflag
|| Bflag
) && first
> 0 &&
270 ( (Bflag
<= linesqueued
&& tail
== 0) || newfile
) )
279 printline(l
, fn_colonchar
, matches
, m
);
281 printline(l
, fn_dashchar
, matches
, m
);
290 grep_malloc(size_t size
)
294 if ((ptr
= malloc(size
)) == NULL
)
300 grep_realloc(void *ptr
, size_t size
)
302 if ((ptr
= realloc(ptr
, size
)) == NULL
)
308 printline(str_t
*line
, int sep
, regmatch_t
*matches
, int m
)
313 if (output_filenames
) {
314 fputs(line
->file
, stdout
);
320 printf("%d", line
->line_no
);
326 printf("%lu", (unsigned long)line
->off
);
331 if ((oflag
|| colours
) && m
> 0) {
333 for (i
= 0; i
< m
; i
++) {
336 fwrite(line
->dat
+ a
, matches
[i
].rm_so
- a
, 1, stdout
);
339 fprintf(stdout
, "\33[%sm", grep_colour
);
340 fwrite(line
->dat
+ matches
[i
].rm_so
,
341 matches
[i
].rm_eo
- matches
[i
].rm_so
, 1, stdout
);
344 fprintf(stdout
, "\33[00m");
345 a
= matches
[i
].rm_eo
;
350 if (line
->len
- a
> 0)
351 fwrite(line
->dat
+ a
, line
->len
- a
, 1, stdout
);
357 fwrite(line
->dat
, line
->len
, 1, stdout
);
358 putchar(line_endchar
);