xref: /freebsd/usr.bin/grep/util.c (revision 77eb877714d69ee0279d70eb3331920fba90db95)
1 /*	$NetBSD: util.c,v 1.9 2011/02/27 17:33:37 joerg Exp $	*/
2 /*	$OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $	*/
3 
4 /*-
5  * SPDX-License-Identifier: BSD-2-Clause
6  *
7  * Copyright (c) 1999 James Howard and Dag-Erling Smørgrav
8  * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
9  * Copyright (C) 2017 Kyle Evans <kevans@FreeBSD.org>
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 
38 #include <ctype.h>
39 #include <err.h>
40 #include <errno.h>
41 #include <fnmatch.h>
42 #include <fts.h>
43 #include <libgen.h>
44 #include <stdbool.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <wchar.h>
50 #include <wctype.h>
51 
52 #include "grep.h"
53 
54 static bool	 first_match = true;
55 
56 /*
57  * Match printing context
58  */
59 struct mprintc {
60 	long long	tail;		/* Number of trailing lines to record */
61 	int		last_outed;	/* Number of lines since last output */
62 	bool		doctx;		/* Printing context? */
63 	bool		printmatch;	/* Printing matches? */
64 	bool		same_file;	/* Same file as previously printed? */
65 };
66 
67 static void procmatch_match(struct mprintc *mc, struct parsec *pc);
68 static void procmatch_nomatch(struct mprintc *mc, struct parsec *pc);
69 static bool procmatches(struct mprintc *mc, struct parsec *pc, bool matched);
70 #ifdef WITH_INTERNAL_NOSPEC
71 static int litexec(const struct pat *pat, const char *string,
72     size_t nmatch, regmatch_t pmatch[]);
73 #endif
74 static bool procline(struct parsec *pc);
75 static void printline(struct parsec *pc, int sep);
76 static void printline_metadata(struct str *line, int sep);
77 
78 bool
file_matching(const char * fname)79 file_matching(const char *fname)
80 {
81 	char *fname_base, *fname_buf;
82 	bool ret;
83 
84 	ret = finclude ? false : true;
85 	fname_buf = strdup(fname);
86 	if (fname_buf == NULL)
87 		err(2, "strdup");
88 	fname_base = basename(fname_buf);
89 
90 	for (unsigned int i = 0; i < fpatterns; ++i) {
91 		if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
92 		    fnmatch(fpattern[i].pat, fname_base, 0) == 0)
93 			/*
94 			 * The last pattern matched wins exclusion/inclusion
95 			 * rights, so we can't reasonably bail out early here.
96 			 */
97 			ret = (fpattern[i].mode != EXCL_PAT);
98 	}
99 	free(fname_buf);
100 	return (ret);
101 }
102 
103 static inline bool
dir_matching(const char * dname)104 dir_matching(const char *dname)
105 {
106 	bool ret;
107 
108 	ret = dinclude ? false : true;
109 
110 	for (unsigned int i = 0; i < dpatterns; ++i) {
111 		if (dname != NULL && fnmatch(dpattern[i].pat, dname, 0) == 0)
112 			/*
113 			 * The last pattern matched wins exclusion/inclusion
114 			 * rights, so we can't reasonably bail out early here.
115 			 */
116 			ret = (dpattern[i].mode != EXCL_PAT);
117 	}
118 	return (ret);
119 }
120 
121 /*
122  * Processes a directory when a recursive search is performed with
123  * the -R option.  Each appropriate file is passed to procfile().
124  */
125 bool
grep_tree(char ** argv)126 grep_tree(char **argv)
127 {
128 	FTS *fts;
129 	FTSENT *p;
130 	int fts_flags;
131 	bool matched, ok;
132 	const char *wd[] = { ".", NULL };
133 
134 	matched = false;
135 
136 	/* This switch effectively initializes 'fts_flags' */
137 	switch(linkbehave) {
138 	case LINK_EXPLICIT:
139 		fts_flags = FTS_COMFOLLOW | FTS_PHYSICAL;
140 		break;
141 	case LINK_SKIP:
142 		fts_flags = FTS_PHYSICAL;
143 		break;
144 	default:
145 		fts_flags = FTS_LOGICAL | FTS_NOSTAT;
146 	}
147 
148 	fts_flags |= FTS_NOCHDIR;
149 
150 	fts = fts_open((argv[0] == NULL) ?
151 	    __DECONST(char * const *, wd) : argv, fts_flags, NULL);
152 	if (fts == NULL)
153 		err(2, "fts_open");
154 	while (errno = 0, (p = fts_read(fts)) != NULL) {
155 		switch (p->fts_info) {
156 		case FTS_DNR:
157 		case FTS_ERR:
158 		case FTS_NS:
159 			file_err = true;
160 			if(!sflag)
161 				warnc(p->fts_errno, "%s", p->fts_path);
162 			break;
163 		case FTS_D:
164 			if (dexclude || dinclude)
165 				if (!dir_matching(p->fts_name) ||
166 				    !dir_matching(p->fts_path))
167 					fts_set(fts, p, FTS_SKIP);
168 			break;
169 		case FTS_DC:
170 			/* Print a warning for recursive directory loop */
171 			warnx("warning: %s: recursive directory loop",
172 			    p->fts_path);
173 			break;
174 		case FTS_DP:
175 			break;
176 		case FTS_SL:
177 			/*
178 			 * Skip symlinks for LINK_EXPLICIT and
179 			 * LINK_SKIP.  Note that due to FTS_COMFOLLOW,
180 			 * symlinks on the command line are followed
181 			 * for LINK_EXPLICIT and not reported as
182 			 * symlinks.
183 			 */
184 			break;
185 		default:
186 			/* Check for file exclusion/inclusion */
187 			ok = true;
188 			if (fexclude || finclude)
189 				ok &= file_matching(p->fts_path);
190 
191 			if (ok && procfile(p->fts_path))
192 				matched = true;
193 			break;
194 		}
195 	}
196 	if (errno != 0)
197 		err(2, "fts_read");
198 
199 	fts_close(fts);
200 	return (matched);
201 }
202 
203 static void
procmatch_match(struct mprintc * mc,struct parsec * pc)204 procmatch_match(struct mprintc *mc, struct parsec *pc)
205 {
206 
207 	if (mc->doctx) {
208 		if (!first_match && (!mc->same_file || mc->last_outed > 0))
209 			printf("--\n");
210 		if (Bflag > 0)
211 			printqueue();
212 		mc->tail = Aflag;
213 	}
214 
215 	/* Print the matching line, but only if not quiet/binary */
216 	if (mc->printmatch) {
217 		printline(pc, ':');
218 		while (pc->matchidx >= MAX_MATCHES) {
219 			/* Reset matchidx and try again */
220 			pc->matchidx = 0;
221 			if (procline(pc) == !vflag)
222 				printline(pc, ':');
223 			else
224 				break;
225 		}
226 		first_match = false;
227 		mc->same_file = true;
228 		mc->last_outed = 0;
229 	}
230 }
231 
232 static void
procmatch_nomatch(struct mprintc * mc,struct parsec * pc)233 procmatch_nomatch(struct mprintc *mc, struct parsec *pc)
234 {
235 
236 	/* Deal with any -A context as needed */
237 	if (mc->tail > 0) {
238 		grep_printline(&pc->ln, '-');
239 		mc->tail--;
240 		if (Bflag > 0)
241 			clearqueue();
242 	} else if (Bflag == 0 || (Bflag > 0 && enqueue(&pc->ln)))
243 		/*
244 		 * Enqueue non-matching lines for -B context. If we're not
245 		 * actually doing -B context or if the enqueue resulted in a
246 		 * line being rotated out, then go ahead and increment
247 		 * last_outed to signify a gap between context/match.
248 		 */
249 		++mc->last_outed;
250 }
251 
252 /*
253  * Process any matches in the current parsing context, return a boolean
254  * indicating whether we should halt any further processing or not. 'true' to
255  * continue processing, 'false' to halt.
256  */
257 static bool
procmatches(struct mprintc * mc,struct parsec * pc,bool matched)258 procmatches(struct mprintc *mc, struct parsec *pc, bool matched)
259 {
260 
261 	if (mflag && mcount <= 0) {
262 		/*
263 		 * We already hit our match count, but we need to keep dumping
264 		 * lines until we've lost our tail.
265 		 */
266 		grep_printline(&pc->ln, '-');
267 		mc->tail--;
268 		return (mc->tail != 0);
269 	}
270 
271 	/*
272 	 * XXX TODO: This should loop over pc->matches and handle things on a
273 	 * line-by-line basis, setting up a `struct str` as needed.
274 	 */
275 	/* Deal with any -B context or context separators */
276 	if (matched) {
277 		procmatch_match(mc, pc);
278 
279 		/* Count the matches if we have a match limit */
280 		if (mflag) {
281 			/* XXX TODO: Decrement by number of matched lines */
282 			mcount -= 1;
283 			if (mcount <= 0)
284 				return (mc->tail != 0);
285 		}
286 	} else if (mc->doctx)
287 		procmatch_nomatch(mc, pc);
288 
289 	return (true);
290 }
291 
292 /*
293  * Opens a file and processes it.  Each file is processed line-by-line
294  * passing the lines to procline().
295  */
296 bool
procfile(const char * fn)297 procfile(const char *fn)
298 {
299 	struct parsec pc;
300 	struct mprintc mc;
301 	struct file *f;
302 	struct stat sb;
303 	mode_t s;
304 	int lines;
305 	bool line_matched;
306 
307 	if (strcmp(fn, "-") == 0) {
308 		fn = label != NULL ? label : errstr[1];
309 		f = grep_open(NULL);
310 	} else {
311 		if (stat(fn, &sb) == 0) {
312 			/* Check if we need to process the file */
313 			s = sb.st_mode & S_IFMT;
314 			if (dirbehave == DIR_SKIP && s == S_IFDIR)
315 				return (false);
316 			if (devbehave == DEV_SKIP && (s == S_IFIFO ||
317 			    s == S_IFCHR || s == S_IFBLK || s == S_IFSOCK))
318 				return (false);
319 		}
320 		f = grep_open(fn);
321 	}
322 	if (f == NULL) {
323 		file_err = true;
324 		if (!sflag)
325 			warn("%s", fn);
326 		return (false);
327 	}
328 
329 	pc.ln.file = grep_strdup(fn);
330 	pc.ln.line_no = 0;
331 	pc.ln.len = 0;
332 	pc.ln.boff = 0;
333 	pc.ln.off = -1;
334 	pc.binary = f->binary;
335 	pc.cntlines = false;
336 	memset(&mc, 0, sizeof(mc));
337 	mc.printmatch = true;
338 	if ((pc.binary && binbehave == BINFILE_BIN) || cflag || qflag ||
339 	    lflag || Lflag)
340 		mc.printmatch = false;
341 	if (mc.printmatch && (Aflag != 0 || Bflag != 0))
342 		mc.doctx = true;
343 	if (mc.printmatch && (Aflag != 0 || Bflag != 0 || mflag || nflag))
344 		pc.cntlines = true;
345 	mcount = mlimit;
346 
347 	for (lines = 0; lines == 0 || !(lflag || qflag); ) {
348 		/*
349 		 * XXX TODO: We need to revisit this in a chunking world. We're
350 		 * not going to be doing per-line statistics because of the
351 		 * overhead involved. procmatches can figure that stuff out as
352 		 * needed. */
353 		/* Reset per-line statistics */
354 		pc.printed = 0;
355 		pc.matchidx = 0;
356 		pc.lnstart = 0;
357 		pc.ln.boff = 0;
358 		pc.ln.off += pc.ln.len + 1;
359 		/* XXX TODO: Grab a chunk */
360 		if ((pc.ln.dat = grep_fgetln(f, &pc)) == NULL ||
361 		    pc.ln.len == 0)
362 			break;
363 
364 		if (pc.ln.len > 0 && pc.ln.dat[pc.ln.len - 1] == fileeol)
365 			--pc.ln.len;
366 		pc.ln.line_no++;
367 
368 		/* Return if we need to skip a binary file */
369 		if (pc.binary && binbehave == BINFILE_SKIP) {
370 			grep_close(f);
371 			free(pc.ln.file);
372 			free(f);
373 			return (0);
374 		}
375 
376 		if (mflag && mcount <= 0) {
377 			/*
378 			 * Short-circuit, already hit match count and now we're
379 			 * just picking up any remaining pieces.
380 			 */
381 			if (!procmatches(&mc, &pc, false))
382 				break;
383 			continue;
384 		}
385 		line_matched = procline(&pc) == !vflag;
386 		if (line_matched)
387 			++lines;
388 
389 		/* Halt processing if we hit our match limit */
390 		if (!procmatches(&mc, &pc, line_matched))
391 			break;
392 	}
393 	if (Bflag > 0)
394 		clearqueue();
395 	grep_close(f);
396 
397 	if (cflag && !qflag) {
398 		if (!hflag)
399 			printf("%s:", pc.ln.file);
400 		printf("%u\n", lines);
401 	}
402 	if (lflag && !qflag && lines != 0)
403 		printf("%s%c", fn, nullflag ? 0 : '\n');
404 	if (Lflag && !qflag && lines == 0)
405 		printf("%s%c", fn, nullflag ? 0 : '\n');
406 	if (lines != 0 && !cflag && !lflag && !Lflag &&
407 	    binbehave == BINFILE_BIN && f->binary && !qflag)
408 		printf(errstr[7], fn);
409 
410 	free(pc.ln.file);
411 	free(f);
412 	return (lines != 0);
413 }
414 
415 #ifdef WITH_INTERNAL_NOSPEC
416 /*
417  * Internal implementation of literal string search within a string, modeled
418  * after regexec(3), for use when the regex(3) implementation doesn't offer
419  * either REG_NOSPEC or REG_LITERAL. This does not apply in the default FreeBSD
420  * config, but in other scenarios such as building against libgnuregex or on
421  * some non-FreeBSD OSes.
422  */
423 static int
litexec(const struct pat * pat,const char * string,size_t nmatch,regmatch_t pmatch[])424 litexec(const struct pat *pat, const char *string, size_t nmatch,
425     regmatch_t pmatch[])
426 {
427 	char *(*strstr_fn)(const char *, const char *);
428 	char *sub, *subject;
429 	const char *search;
430 	size_t idx, n, ofs, stringlen;
431 
432 	if (cflags & REG_ICASE)
433 		strstr_fn = strcasestr;
434 	else
435 		strstr_fn = strstr;
436 	idx = 0;
437 	ofs = pmatch[0].rm_so;
438 	stringlen = pmatch[0].rm_eo;
439 	if (ofs >= stringlen)
440 		return (REG_NOMATCH);
441 	subject = strndup(string, stringlen);
442 	if (subject == NULL)
443 		return (REG_ESPACE);
444 	for (n = 0; ofs < stringlen;) {
445 		search = (subject + ofs);
446 		if ((unsigned long)pat->len > strlen(search))
447 			break;
448 		sub = strstr_fn(search, pat->pat);
449 		/*
450 		 * Ignoring the empty string possibility due to context: grep optimizes
451 		 * for empty patterns and will never reach this point.
452 		 */
453 		if (sub == NULL)
454 			break;
455 		++n;
456 		/* Fill in pmatch if necessary */
457 		if (nmatch > 0) {
458 			pmatch[idx].rm_so = ofs + (sub - search);
459 			pmatch[idx].rm_eo = pmatch[idx].rm_so + pat->len;
460 			if (++idx == nmatch)
461 				break;
462 			ofs = pmatch[idx].rm_so + 1;
463 		} else
464 			/* We only needed to know if we match or not */
465 			break;
466 	}
467 	free(subject);
468 	if (n > 0 && nmatch > 0)
469 		for (n = idx; n < nmatch; ++n)
470 			pmatch[n].rm_so = pmatch[n].rm_eo = -1;
471 
472 	return (n > 0 ? 0 : REG_NOMATCH);
473 }
474 #endif /* WITH_INTERNAL_NOSPEC */
475 
476 #define iswword(x)	(iswalnum((x)) || (x) == L'_')
477 
478 /*
479  * Processes a line comparing it with the specified patterns.  Each pattern
480  * is looped to be compared along with the full string, saving each and every
481  * match, which is necessary to colorize the output and to count the
482  * matches.  The matching lines are passed to printline() to display the
483  * appropriate output.
484  */
485 static bool
procline(struct parsec * pc)486 procline(struct parsec *pc)
487 {
488 	regmatch_t pmatch, lastmatch, chkmatch;
489 	wchar_t wbegin, wend;
490 	size_t st, nst;
491 	unsigned int i;
492 	int r = 0, leflags = eflags;
493 	size_t startm = 0, matchidx;
494 	unsigned int retry;
495 	bool lastmatched, matched;
496 
497 	matchidx = pc->matchidx;
498 
499 	/* Null pattern shortcuts. */
500 	if (matchall) {
501 		if (xflag && pc->ln.len == 0) {
502 			/* Matches empty lines (-x). */
503 			return (true);
504 		} else if (!wflag && !xflag) {
505 			/* Matches every line (no -w or -x). */
506 			return (true);
507 		}
508 
509 		/*
510 		 * If we only have the NULL pattern, whether we match or not
511 		 * depends on if we got here with -w or -x.  If either is set,
512 		 * the answer is no.  If we have other patterns, we'll defer
513 		 * to them.
514 		 */
515 		if (patterns == 0) {
516 			return (!(wflag || xflag));
517 		}
518 	} else if (patterns == 0) {
519 		/* Pattern file with no patterns. */
520 		return (false);
521 	}
522 
523 	matched = false;
524 	st = pc->lnstart;
525 	nst = 0;
526 	/* Initialize to avoid a false positive warning from GCC. */
527 	lastmatch.rm_so = lastmatch.rm_eo = 0;
528 
529 	/* Loop to process the whole line */
530 	while (st <= pc->ln.len) {
531 		lastmatched = false;
532 		startm = matchidx;
533 		retry = 0;
534 		if (st > 0 && pc->ln.dat[st - 1] != fileeol)
535 			leflags |= REG_NOTBOL;
536 		/* Loop to compare with all the patterns */
537 		for (i = 0; i < patterns; i++) {
538 			pmatch.rm_so = st;
539 			pmatch.rm_eo = pc->ln.len;
540 #ifdef WITH_INTERNAL_NOSPEC
541 			if (grepbehave == GREP_FIXED)
542 				r = litexec(&pattern[i], pc->ln.dat, 1, &pmatch);
543 			else
544 #endif
545 			r = regexec(&r_pattern[i], pc->ln.dat, 1, &pmatch,
546 			    leflags);
547 			if (r != 0)
548 				continue;
549 			/* Check for full match */
550 			if (xflag && (pmatch.rm_so != 0 ||
551 			    (size_t)pmatch.rm_eo != pc->ln.len))
552 				continue;
553 			/* Check for whole word match */
554 			if (wflag) {
555 				wbegin = wend = L' ';
556 				if (pmatch.rm_so != 0 &&
557 				    sscanf(&pc->ln.dat[pmatch.rm_so - 1],
558 				    "%lc", &wbegin) != 1)
559 					r = REG_NOMATCH;
560 				else if ((size_t)pmatch.rm_eo !=
561 				    pc->ln.len &&
562 				    sscanf(&pc->ln.dat[pmatch.rm_eo],
563 				    "%lc", &wend) != 1)
564 					r = REG_NOMATCH;
565 				else if (iswword(wbegin) ||
566 				    iswword(wend))
567 					r = REG_NOMATCH;
568 				/*
569 				 * If we're doing whole word matching and we
570 				 * matched once, then we should try the pattern
571 				 * again after advancing just past the start of
572 				 * the earliest match. This allows the pattern
573 				 * to  match later on in the line and possibly
574 				 * still match a whole word.
575 				 */
576 				if (r == REG_NOMATCH &&
577 				    (retry == pc->lnstart ||
578 				    (unsigned int)pmatch.rm_so + 1 < retry))
579 					retry = pmatch.rm_so + 1;
580 				if (r == REG_NOMATCH)
581 					continue;
582 			}
583 			lastmatched = true;
584 			lastmatch = pmatch;
585 
586 			if (matchidx == 0)
587 				matched = true;
588 
589 			/*
590 			 * Replace previous match if the new one is earlier
591 			 * and/or longer. This will lead to some amount of
592 			 * extra work if -o/--color are specified, but it's
593 			 * worth it from a correctness point of view.
594 			 */
595 			if (matchidx > startm) {
596 				chkmatch = pc->matches[matchidx - 1];
597 				if (pmatch.rm_so < chkmatch.rm_so ||
598 				    (pmatch.rm_so == chkmatch.rm_so &&
599 				    (pmatch.rm_eo - pmatch.rm_so) >
600 				    (chkmatch.rm_eo - chkmatch.rm_so))) {
601 					pc->matches[matchidx - 1] = pmatch;
602 					nst = pmatch.rm_eo;
603 				}
604 			} else {
605 				/* Advance as normal if not */
606 				pc->matches[matchidx++] = pmatch;
607 				nst = pmatch.rm_eo;
608 			}
609 			/* avoid excessive matching - skip further patterns */
610 			if ((color == NULL && !oflag) || qflag || lflag ||
611 			    matchidx >= MAX_MATCHES) {
612 				pc->lnstart = nst;
613 				lastmatched = false;
614 				break;
615 			}
616 		}
617 
618 		/*
619 		 * Advance to just past the start of the earliest match, try
620 		 * again just in case we still have a chance to match later in
621 		 * the string.
622 		 */
623 		if (!lastmatched && retry > pc->lnstart) {
624 			st = retry;
625 			continue;
626 		}
627 
628 		/* XXX TODO: We will need to keep going, since we're chunky */
629 		/* One pass if we are not recording matches */
630 		if (!wflag && ((color == NULL && !oflag) || qflag || lflag || Lflag))
631 			break;
632 
633 		/* If we didn't have any matches or REG_NOSUB set */
634 		if (!lastmatched || (cflags & REG_NOSUB))
635 			nst = pc->ln.len;
636 
637 		if (!lastmatched)
638 			/* No matches */
639 			break;
640 		else if (st == nst && lastmatch.rm_so == lastmatch.rm_eo)
641 			/* Zero-length match -- advance one more so we don't get stuck */
642 			nst++;
643 
644 		/* Advance st based on previous matches */
645 		st = nst;
646 		pc->lnstart = st;
647 	}
648 
649 	/* Reflect the new matchidx in the context */
650 	pc->matchidx = matchidx;
651 	return matched;
652 }
653 
654 /*
655  * Safe malloc() for internal use.
656  */
657 void *
grep_malloc(size_t size)658 grep_malloc(size_t size)
659 {
660 	void *ptr;
661 
662 	if (size == 0)
663 		return (NULL);
664 	if ((ptr = malloc(size)) == NULL)
665 		err(2, "malloc");
666 	return (ptr);
667 }
668 
669 /*
670  * Safe calloc() for internal use.
671  */
672 void *
grep_calloc(size_t nmemb,size_t size)673 grep_calloc(size_t nmemb, size_t size)
674 {
675 	void *ptr;
676 
677 	if (nmemb == 0 || size == 0)
678 		return (NULL);
679 	if ((ptr = calloc(nmemb, size)) == NULL)
680 		err(2, "calloc");
681 	return (ptr);
682 }
683 
684 /*
685  * Safe realloc() for internal use.
686  */
687 void *
grep_realloc(void * ptr,size_t size)688 grep_realloc(void *ptr, size_t size)
689 {
690 
691 	if ((ptr = realloc(ptr, size)) == NULL)
692 		err(2, "realloc");
693 	return (ptr);
694 }
695 
696 /*
697  * Safe strdup() for internal use.
698  */
699 char *
grep_strdup(const char * str)700 grep_strdup(const char *str)
701 {
702 	char *ret;
703 
704 	if ((ret = strdup(str)) == NULL)
705 		err(2, "strdup");
706 	return (ret);
707 }
708 
709 /*
710  * Print an entire line as-is, there are no inline matches to consider. This is
711  * used for printing context.
712  */
grep_printline(struct str * line,int sep)713 void grep_printline(struct str *line, int sep) {
714 	printline_metadata(line, sep);
715 	fwrite(line->dat, line->len, 1, stdout);
716 	putchar(fileeol);
717 }
718 
719 static void
printline_metadata(struct str * line,int sep)720 printline_metadata(struct str *line, int sep)
721 {
722 	bool printsep;
723 
724 	printsep = false;
725 	if (!hflag) {
726 		if (!nullflag) {
727 			fputs(line->file, stdout);
728 			printsep = true;
729 		} else {
730 			printf("%s", line->file);
731 			putchar(0);
732 		}
733 	}
734 	if (nflag) {
735 		if (printsep)
736 			putchar(sep);
737 		printf("%d", line->line_no);
738 		printsep = true;
739 	}
740 	if (bflag) {
741 		if (printsep)
742 			putchar(sep);
743 		printf("%lld", (long long)(line->off + line->boff));
744 		printsep = true;
745 	}
746 	if (printsep)
747 		putchar(sep);
748 }
749 
750 /*
751  * Prints a matching line according to the command line options.
752  */
753 static void
printline(struct parsec * pc,int sep)754 printline(struct parsec *pc, int sep)
755 {
756 	size_t a = 0;
757 	size_t i, matchidx;
758 	regmatch_t match;
759 
760 	/* If matchall, everything matches but don't actually print for -o */
761 	if (oflag && matchall)
762 		return;
763 
764 	matchidx = pc->matchidx;
765 
766 	/* --color and -o */
767 	if ((oflag || color) && matchidx > 0) {
768 		/* Only print metadata once per line if --color */
769 		if (!oflag && pc->printed == 0)
770 			printline_metadata(&pc->ln, sep);
771 		for (i = 0; i < matchidx; i++) {
772 			match = pc->matches[i];
773 			/* Don't output zero length matches */
774 			if (match.rm_so == match.rm_eo)
775 				continue;
776 			/*
777 			 * Metadata is printed on a per-line basis, so every
778 			 * match gets file metadata with the -o flag.
779 			 */
780 			if (oflag) {
781 				pc->ln.boff = match.rm_so;
782 				printline_metadata(&pc->ln, sep);
783 			} else
784 				fwrite(pc->ln.dat + a, match.rm_so - a, 1,
785 				    stdout);
786 			if (color)
787 				fprintf(stdout, "\33[%sm\33[K", color);
788 			fwrite(pc->ln.dat + match.rm_so,
789 			    match.rm_eo - match.rm_so, 1, stdout);
790 			if (color)
791 				fprintf(stdout, "\33[m\33[K");
792 			a = match.rm_eo;
793 			if (oflag)
794 				putchar('\n');
795 		}
796 		if (!oflag) {
797 			if (pc->ln.len - a > 0)
798 				fwrite(pc->ln.dat + a, pc->ln.len - a, 1,
799 				    stdout);
800 			putchar('\n');
801 		}
802 	} else
803 		grep_printline(&pc->ln, sep);
804 	pc->printed++;
805 }
806