35 /*
36 * grep -- print lines matching (or not matching) a pattern
37 *
38 * status returns:
39 * 0 - ok, and some matches
40 * 1 - ok, but no matches
41 * 2 - some error
42 */
43
44 #include <sys/types.h>
45
46 #include <ctype.h>
47 #include <fcntl.h>
48 #include <locale.h>
49 #include <memory.h>
50 #include <regexpr.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55
56 static const char *errstr[] = {
57 "Range endpoint too large.",
58 "Bad number.",
59 "``\\digit'' out of range.",
60 "No remembered search string.",
61 "\\( \\) imbalance.",
62 "Too many \\(.",
63 "More than 2 numbers given in \\{ \\}.",
64 "} expected after \\.",
65 "First number exceeds second in \\{ \\}.",
66 "[ ] imbalance.",
67 "Regular expression overflow.",
68 "Illegal byte sequence.",
69 "Unknown regexp error code!!",
70 NULL
71 };
72
73 #define errmsg(msg, arg) (void) fprintf(stderr, gettext(msg), arg)
74 #define BLKSIZE 512
75 #define GBUFSIZ 8192
76
77 static int temp;
78 static long long lnum;
79 static char *linebuf;
80 static char *prntbuf = NULL;
81 static long fw_lPrntBufLen = 0;
82 static int nflag;
83 static int bflag;
84 static int lflag;
85 static int cflag;
86 static int vflag;
87 static int sflag;
88 static int iflag;
89 static int wflag;
90 static int hflag;
91 static int qflag;
92 static int errflg;
93 static int nfile;
94 static long long tln;
95 static int nsucc;
96 static int nlflag;
97 static char *ptr, *ptrend;
98 static char *expbuf;
99
100 static void execute(char *);
101 static void regerr(int);
102 static int succeed(char *);
103
104 int
105 main(int argc, char **argv)
106 {
107 int c;
108 char *arg;
109 extern int optind;
110
111 (void) setlocale(LC_ALL, "");
112 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
113 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
114 #endif
115 (void) textdomain(TEXT_DOMAIN);
116
117 while ((c = getopt(argc, argv, "hqblcnsviyw")) != -1)
118 switch (c) {
119 case 'h':
120 hflag++;
121 break;
122 case 'q': /* POSIX: quiet: status only */
123 qflag++;
124 break;
125 case 'v':
126 vflag++;
127 break;
128 case 'c':
129 cflag++;
130 break;
131 case 'n':
132 nflag++;
133 break;
134 case 'b':
135 bflag++;
136 break;
137 case 's':
138 sflag++;
139 break;
140 case 'l':
141 lflag++;
142 break;
143 case 'y':
144 case 'i':
145 iflag++;
146 break;
147 case 'w':
148 wflag++;
149 break;
150 case '?':
151 errflg++;
152 }
153
154 if (errflg || (optind >= argc)) {
155 errmsg("Usage: grep [-c|-l|-q] -hbnsviw pattern file . . .\n",
156 (char *)NULL);
157 exit(2);
158 }
159
160 argv = &argv[optind];
161 argc -= optind;
162 nfile = argc - 1;
163
164 if (strrchr(*argv, '\n') != NULL)
165 regerr(41);
166
167 if (iflag) {
168 for (arg = *argv; *arg != NULL; ++arg)
169 *arg = (char)tolower((int)((unsigned char)*arg));
170 }
171
172 if (wflag) {
173 unsigned int wordlen;
174 char *wordbuf;
175
176 wordlen = strlen(*argv) + 5; /* '\\' '<' *argv '\\' '>' '\0' */
177 if ((wordbuf = malloc(wordlen)) == NULL) {
178 errmsg("grep: Out of memory for word\n", (char *)NULL);
179 exit(2);
180 }
181
182 (void) strcpy(wordbuf, "\\<");
183 (void) strcat(wordbuf, *argv);
184 (void) strcat(wordbuf, "\\>");
185 *argv = wordbuf;
186 }
187
188 expbuf = compile(*argv, (char *)0, (char *)0);
189 if (regerrno)
190 regerr(regerrno);
191
192 if (--argc == 0)
193 execute(NULL);
194 else
195 while (argc-- > 0)
196 execute(*++argv);
197
198 return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
199 }
200
201 static void
202 execute(char *file)
203 {
204 char *lbuf, *p;
205 long count;
206 long offset = 0;
207 char *next_ptr = NULL;
208 long next_count = 0;
209
210 tln = 0;
211
212 if (prntbuf == NULL) {
213 fw_lPrntBufLen = GBUFSIZ + 1;
214 if ((prntbuf = malloc(fw_lPrntBufLen)) == NULL) {
215 exit(2); /* out of memory - BAIL */
216 }
217 if ((linebuf = malloc(fw_lPrntBufLen)) == NULL) {
218 exit(2); /* out of memory - BAIL */
219 }
220 }
221
222 if (file == NULL)
223 temp = 0;
224 else if ((temp = open(file, O_RDONLY)) == -1) {
225 if (!sflag)
226 errmsg("grep: can't open %s\n", file);
227 nsucc = 2;
228 return;
229 }
230
231 /* read in first block of bytes */
232 if ((count = read(temp, prntbuf, GBUFSIZ)) <= 0) {
233 (void) close(temp);
234
235 if (cflag && !qflag) {
236 if (nfile > 1 && !hflag && file)
237 (void) fprintf(stdout, "%s:", file);
238 (void) fprintf(stdout, "%lld\n", tln);
239 }
240 return;
241 }
242
243 lnum = 0;
244 ptr = prntbuf;
245 for (;;) {
246 /* look for next newline */
247 if ((ptrend = memchr(ptr + offset, '\n', count)) == NULL) {
248 offset += count;
249
250 /*
251 * shift unused data to the beginning of the buffer
252 */
253 if (ptr > prntbuf) {
254 (void) memmove(prntbuf, ptr, offset);
255 ptr = prntbuf;
256 }
257
312 } else
313 /*
314 * Use record as is
315 */
316 lbuf = ptr;
317
318 /* lflag only once */
319 if ((step(lbuf, expbuf) ^ vflag) && succeed(file) == 1)
320 break;
321
322 if (!nlflag)
323 break;
324
325 ptr = next_ptr;
326 count = next_count;
327 offset = 0;
328 }
329 (void) close(temp);
330
331 if (cflag && !qflag) {
332 if (nfile > 1 && !hflag && file)
333 (void) fprintf(stdout, "%s:", file);
334 (void) fprintf(stdout, "%lld\n", tln);
335 }
336 }
337
338 static int
339 succeed(char *f)
340 {
341 int nchars;
342 nsucc = (nsucc == 2) ? 2 : 1;
343
344 if (f == NULL)
345 f = "<stdin>";
346
347 if (qflag) {
348 /* no need to continue */
349 return (1);
350 }
351
352 if (cflag) {
353 tln++;
354 return (0);
355 }
356
357 if (lflag) {
358 (void) fprintf(stdout, "%s\n", f);
359 return (1);
360 }
361
362 if (nfile > 1 && !hflag)
363 /* print filename */
364 (void) fprintf(stdout, "%s:", f);
365
366 if (bflag)
367 /* print block number */
368 (void) fprintf(stdout, "%lld:", (offset_t)
369 ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));
370
371 if (nflag)
372 /* print line number */
373 (void) fprintf(stdout, "%lld:", lnum);
374
375 if (nlflag) {
376 /* newline at end of line */
377 *ptrend = '\n';
378 nchars = ptrend - ptr + 1;
379 } else {
380 /* don't write sentinel \0 */
381 nchars = ptrend - ptr;
382 }
383
384 (void) fwrite(ptr, 1, nchars, stdout);
|
35 /*
36 * grep -- print lines matching (or not matching) a pattern
37 *
38 * status returns:
39 * 0 - ok, and some matches
40 * 1 - ok, but no matches
41 * 2 - some error
42 */
43
44 #include <sys/types.h>
45
46 #include <ctype.h>
47 #include <fcntl.h>
48 #include <locale.h>
49 #include <memory.h>
50 #include <regexpr.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 #include <ftw.h>
56 #include <limits.h>
57 #include <sys/param.h>
58
59 static const char *errstr[] = {
60 "Range endpoint too large.",
61 "Bad number.",
62 "``\\digit'' out of range.",
63 "No remembered search string.",
64 "\\( \\) imbalance.",
65 "Too many \\(.",
66 "More than 2 numbers given in \\{ \\}.",
67 "} expected after \\.",
68 "First number exceeds second in \\{ \\}.",
69 "[ ] imbalance.",
70 "Regular expression overflow.",
71 "Illegal byte sequence.",
72 "Unknown regexp error code!!",
73 NULL
74 };
75
76 #define errmsg(msg, arg) (void) fprintf(stderr, gettext(msg), arg)
77 #define BLKSIZE 512
78 #define GBUFSIZ 8192
79 #define MAX_DEPTH 1000
80
81 static int temp;
82 static long long lnum;
83 static char *linebuf;
84 static char *prntbuf = NULL;
85 static long fw_lPrntBufLen = 0;
86 static int nflag;
87 static int bflag;
88 static int lflag;
89 static int cflag;
90 static int rflag;
91 static int Rflag;
92 static int vflag;
93 static int sflag;
94 static int iflag;
95 static int wflag;
96 static int hflag;
97 static int qflag;
98 static int errflg;
99 static int nfile;
100 static long long tln;
101 static int nsucc;
102 static int outfn = 0;
103 static int nlflag;
104 static char *ptr, *ptrend;
105 static char *expbuf;
106
107 static void execute(const char *, int);
108 static void regerr(int);
109 static void prepare(const char *);
110 static int recursive(const char *, const struct stat *, int, struct FTW *);
111 static int succeed(const char *);
112
113 int
114 main(int argc, char **argv)
115 {
116 int c;
117 char *arg;
118 extern int optind;
119
120 (void) setlocale(LC_ALL, "");
121 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
122 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
123 #endif
124 (void) textdomain(TEXT_DOMAIN);
125
126 while ((c = getopt(argc, argv, "hqblcnRrsviyw")) != -1)
127 switch (c) {
128 case 'h':
129 hflag++;
130 break;
131 case 'q': /* POSIX: quiet: status only */
132 qflag++;
133 break;
134 case 'v':
135 vflag++;
136 break;
137 case 'c':
138 cflag++;
139 break;
140 case 'n':
141 nflag++;
142 break;
143 case 'R':
144 Rflag++;
145 /* FALLTHROUGH */
146 case 'r':
147 rflag++;
148 break;
149 case 'b':
150 bflag++;
151 break;
152 case 's':
153 sflag++;
154 break;
155 case 'l':
156 lflag++;
157 break;
158 case 'y':
159 case 'i':
160 iflag++;
161 break;
162 case 'w':
163 wflag++;
164 break;
165 case '?':
166 errflg++;
167 }
168
169 if (errflg || (optind >= argc)) {
170 errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hbnsviw "
171 "pattern file . . .\n",
172 (char *)NULL);
173 exit(2);
174 }
175
176 argv = &argv[optind];
177 argc -= optind;
178 nfile = argc - 1;
179
180 if (strrchr(*argv, '\n') != NULL)
181 regerr(41);
182
183 if (iflag) {
184 for (arg = *argv; *arg != NULL; ++arg)
185 *arg = (char)tolower((int)((unsigned char)*arg));
186 }
187
188 if (wflag) {
189 unsigned int wordlen;
190 char *wordbuf;
191
192 wordlen = strlen(*argv) + 5; /* '\\' '<' *argv '\\' '>' '\0' */
193 if ((wordbuf = malloc(wordlen)) == NULL) {
194 errmsg("grep: Out of memory for word\n", (char *)NULL);
195 exit(2);
196 }
197
198 (void) strcpy(wordbuf, "\\<");
199 (void) strcat(wordbuf, *argv);
200 (void) strcat(wordbuf, "\\>");
201 *argv = wordbuf;
202 }
203
204 expbuf = compile(*argv, (char *)0, (char *)0);
205 if (regerrno)
206 regerr(regerrno);
207
208 if (--argc == 0)
209 execute(NULL, 0);
210 else
211 while (argc-- > 0)
212 prepare(*++argv);
213
214 return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
215 }
216
217 static void
218 prepare(const char *path)
219 {
220 struct stat st;
221 int walkflags = FTW_CHDIR;
222 char *buf = NULL;
223
224 if (rflag) {
225 if (stat(path, &st) != -1 &&
226 (st.st_mode & S_IFMT) == S_IFDIR) {
227 outfn = 1;
228
229 /*
230 * Add trailing slash if arg
231 * is directory, to resolve symlinks.
232 */
233 if (path[strlen(path) - 1] != '/') {
234 (void) asprintf(&buf, "%s/", path);
235 if (buf != NULL)
236 path = buf;
237 }
238
239 /*
240 * Search through subdirs if path is directory.
241 * Don't follow symlinks if Rflag is not set.
242 */
243 if (!Rflag)
244 walkflags |= FTW_PHYS;
245
246 if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) {
247 if (!sflag)
248 errmsg("grep: can't open %s\n", path);
249 nsucc = 2;
250 }
251 return;
252 }
253 }
254 execute(path, 0);
255 }
256
257 static int
258 recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw)
259 {
260 /*
261 * process files and follow symlinks if Rflag set.
262 */
263 if (info != FTW_F) {
264 if (!sflag &&
265 (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) {
266 /* report broken symlinks and unreadable files */
267 errmsg("grep: can't open %s\n", name);
268 }
269 return (0);
270 }
271
272 /* skip devices and pipes if Rflag is not set */
273 if (!Rflag && !S_ISREG(statp->st_mode))
274 return (0);
275
276 /* pass offset to relative name from FTW_CHDIR */
277 execute(name, ftw->base);
278 return (0);
279 }
280
281 static void
282 execute(const char *file, int base)
283 {
284 char *lbuf, *p;
285 long count;
286 long offset = 0;
287 char *next_ptr = NULL;
288 long next_count = 0;
289
290 tln = 0;
291
292 if (prntbuf == NULL) {
293 fw_lPrntBufLen = GBUFSIZ + 1;
294 if ((prntbuf = malloc(fw_lPrntBufLen)) == NULL) {
295 exit(2); /* out of memory - BAIL */
296 }
297 if ((linebuf = malloc(fw_lPrntBufLen)) == NULL) {
298 exit(2); /* out of memory - BAIL */
299 }
300 }
301
302 if (file == NULL)
303 temp = 0;
304 else if ((temp = open(file + base, O_RDONLY)) == -1) {
305 if (!sflag)
306 errmsg("grep: can't open %s\n", file);
307 nsucc = 2;
308 return;
309 }
310
311 /* read in first block of bytes */
312 if ((count = read(temp, prntbuf, GBUFSIZ)) <= 0) {
313 (void) close(temp);
314
315 if (cflag && !qflag) {
316 if (nfile > 1 && !hflag && file)
317 (void) fprintf(stdout, "%s:", file);
318 if (!rflag)
319 (void) fprintf(stdout, "%lld\n", tln);
320 }
321 return;
322 }
323
324 lnum = 0;
325 ptr = prntbuf;
326 for (;;) {
327 /* look for next newline */
328 if ((ptrend = memchr(ptr + offset, '\n', count)) == NULL) {
329 offset += count;
330
331 /*
332 * shift unused data to the beginning of the buffer
333 */
334 if (ptr > prntbuf) {
335 (void) memmove(prntbuf, ptr, offset);
336 ptr = prntbuf;
337 }
338
393 } else
394 /*
395 * Use record as is
396 */
397 lbuf = ptr;
398
399 /* lflag only once */
400 if ((step(lbuf, expbuf) ^ vflag) && succeed(file) == 1)
401 break;
402
403 if (!nlflag)
404 break;
405
406 ptr = next_ptr;
407 count = next_count;
408 offset = 0;
409 }
410 (void) close(temp);
411
412 if (cflag && !qflag) {
413 if (!hflag && file && (nfile > 1 ||
414 (rflag && outfn)))
415 (void) fprintf(stdout, "%s:", file);
416 (void) fprintf(stdout, "%lld\n", tln);
417 }
418 }
419
420 static int
421 succeed(const char *f)
422 {
423 int nchars;
424 nsucc = (nsucc == 2) ? 2 : 1;
425
426 if (f == NULL)
427 f = "<stdin>";
428
429 if (qflag) {
430 /* no need to continue */
431 return (1);
432 }
433
434 if (cflag) {
435 tln++;
436 return (0);
437 }
438
439 if (lflag) {
440 (void) fprintf(stdout, "%s\n", f);
441 return (1);
442 }
443
444 if (!hflag && (nfile > 1 || (rflag && outfn))) {
445 /* print filename */
446 (void) fprintf(stdout, "%s:", f);
447 }
448
449 if (bflag)
450 /* print block number */
451 (void) fprintf(stdout, "%lld:", (offset_t)
452 ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));
453
454 if (nflag)
455 /* print line number */
456 (void) fprintf(stdout, "%lld:", lnum);
457
458 if (nlflag) {
459 /* newline at end of line */
460 *ptrend = '\n';
461 nchars = ptrend - ptr + 1;
462 } else {
463 /* don't write sentinel \0 */
464 nchars = ptrend - ptr;
465 }
466
467 (void) fwrite(ptr, 1, nchars, stdout);
|