util.c revision 1.1 1 /*-
2 * Copyright (c) 1999 James Howard and Dag-Erling Codan Smrgrav
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 AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: util.c,v 1.1 2004/01/02 14:58:43 cjep Exp $
27 */
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31
32 #include <ctype.h>
33 #include <err.h>
34 #include <errno.h>
35 #include <fts.h>
36 #include <regex.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <zlib.h>
42
43 #include "grep.h"
44
45 /*
46 * Process a file line by line...
47 */
48
49 static int linesqueued;
50 static int procline(str_t *l);
51
52 int
53 grep_tree(char **argv)
54 {
55 FTS *fts;
56 FTSENT *p;
57 int c, fts_flags;
58
59 c = fts_flags = 0;
60
61 if (Hflag)
62 fts_flags = FTS_COMFOLLOW;
63 if (Pflag)
64 fts_flags = FTS_PHYSICAL;
65 if (Sflag)
66 fts_flags = FTS_LOGICAL;
67
68 fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
69
70 if (!(fts = fts_open(argv, fts_flags, (int (*) ()) NULL)))
71 err(1, NULL);
72 while ((p = fts_read(fts)) != NULL) {
73 switch (p->fts_info) {
74 case FTS_DNR:
75 break;
76 case FTS_ERR:
77 errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
78 break;
79 case FTS_DP:
80 break;
81 default:
82 c += procfile(p->fts_path);
83 break;
84 }
85 }
86
87 return c;
88 }
89
90 int
91 procfile(char *fn)
92 {
93 str_t ln;
94 file_t *f;
95 int c, t, z;
96
97 if (fn == NULL) {
98 fn = "(standard input)";
99 f = grep_fdopen(STDIN_FILENO, "r");
100 } else {
101 f = grep_open(fn, "r");
102 }
103 if (f == NULL) {
104 if (!sflag)
105 warn("%s", fn);
106 return 0;
107 }
108 if (aflag && grep_bin_file(f)) {
109 grep_close(f);
110 return 0;
111 }
112
113 ln.file = fn;
114 ln.line_no = 0;
115 linesqueued = 0;
116 ln.off = -1;
117
118 if (Bflag > 0)
119 initqueue();
120 for (c = 0; !(lflag && c);) {
121 ln.off += ln.len + 1;
122 if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL)
123 break;
124 if (ln.len > 0 && ln.dat[ln.len - 1] == '\n')
125 --ln.len;
126 ln.line_no++;
127
128 z = tail;
129
130 if ((t = procline(&ln)) == 0 && Bflag > 0 && z == 0) {
131 enqueue(&ln);
132 linesqueued++;
133 }
134 c += t;
135 }
136 if (Bflag > 0)
137 clearqueue();
138 grep_close(f);
139
140 if (cflag) {
141 if (!hflag)
142 printf("%s:", ln.file);
143 printf("%u\n", c);
144 }
145 if (lflag && c != 0)
146 printf("%s\n", fn);
147 if (Lflag && c == 0)
148 printf("%s\n", fn);
149 return c;
150 }
151
152
153 /*
154 * Process an individual line in a file. Return non-zero if it matches.
155 */
156
157 #define isword(x) (isalnum(x) || (x) == '_')
158
159 static int
160 procline(str_t *l)
161 {
162 regmatch_t pmatch;
163 int c, i, r, t;
164
165 if (matchall) {
166 c = !vflag;
167 goto print;
168 }
169
170 t = vflag ? REG_NOMATCH : 0;
171 pmatch.rm_so = 0;
172 pmatch.rm_eo = l->len;
173 for (c = i = 0; i < patterns; i++) {
174 r = regexec(&r_pattern[i], l->dat, 0, &pmatch, eflags);
175 if (r == REG_NOMATCH && t == 0)
176 continue;
177 if (r == 0) {
178 if (wflag) {
179 if ((pmatch.rm_so != 0 && isword(l->dat[pmatch.rm_so - 1]))
180 || (pmatch.rm_eo != l->len && isword(l->dat[pmatch.rm_eo])))
181 r = REG_NOMATCH;
182 }
183 if (xflag) {
184 if (pmatch.rm_so != 0 || pmatch.rm_eo != l->len)
185 r = REG_NOMATCH;
186 }
187 }
188 if (r == t) {
189 c++;
190 break;
191 }
192 }
193
194 print:
195 if ((tail > 0 || c) && !cflag && !qflag) {
196 if (c) {
197 if (first > 0 && tail == 0 && (Bflag < linesqueued) && (Aflag || Bflag))
198 printf("--\n");
199 first = 1;
200 tail = Aflag;
201 if (Bflag > 0)
202 printqueue();
203 linesqueued = 0;
204 printline(l, ':');
205 } else {
206 printline(l, '-');
207 tail--;
208 }
209 }
210 return c;
211 }
212
213 void *
214 grep_malloc(size_t size)
215 {
216 void *ptr;
217
218 if ((ptr = malloc(size)) == NULL)
219 err(1, "malloc");
220 return ptr;
221 }
222
223 void *
224 grep_realloc(void *ptr, size_t size)
225 {
226 if ((ptr = realloc(ptr, size)) == NULL)
227 err(1, "realloc");
228 return ptr;
229 }
230
231 void
232 printline(str_t *line, int sep)
233 {
234 int n;
235
236 n = 0;
237 if (!hflag) {
238 fputs(line->file, stdout);
239 ++n;
240 }
241 if (nflag) {
242 if (n)
243 putchar(sep);
244 printf("%d", line->line_no);
245 ++n;
246 }
247 if (bflag) {
248 if (n)
249 putchar(sep);
250 printf("%lu", (unsigned long)line->off);
251 }
252 if (n)
253 putchar(sep);
254 fwrite(line->dat, line->len, 1, stdout);
255 putchar('\n');
256 }
257