From 1fd6e0f27a1b79aefcbc7bda5f618c8c59842dce Mon Sep 17 00:00:00 2001 From: op Date: Sun, 26 Jun 2022 10:57:36 +0000 Subject: [PATCH] grep: add --null flag makes grep print an ASCII NUL byte after the file name to make the output unambiguous even in the presence of file names with funny characters. A previous iteration of this diff was improved by benno@ and tedu@ and discussed also with sthen@ and deraadt@. deraadt@ also improved the manpage changes in this version of the diff. OK deraadt@ --- usr.bin/grep/grep.1 | 14 ++++++++++++-- usr.bin/grep/grep.c | 8 +++++++- usr.bin/grep/grep.h | 4 ++-- usr.bin/grep/util.c | 21 +++++++++++++-------- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/usr.bin/grep/grep.1 b/usr.bin/grep/grep.1 index 5cc228df222..8701df169f6 100644 --- a/usr.bin/grep/grep.1 +++ b/usr.bin/grep/grep.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: grep.1,v 1.50 2019/12/03 08:48:49 kn Exp $ +.\" $OpenBSD: grep.1,v 1.51 2022/06/26 10:57:36 op Exp $ .\" Copyright (c) 1980, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -28,7 +28,7 @@ .\" .\" @(#)grep.1 8.3 (Berkeley) 4/18/94 .\" -.Dd $Mdocdate: December 3 2019 $ +.Dd $Mdocdate: June 26 2022 $ .Dt GREP 1 .Os .Sh NAME @@ -49,6 +49,7 @@ .Op Fl -context Ns Op = Ns Ar num .Op Fl -label Ns = Ns Ar name .Op Fl -line-buffered +.Op Fl -null .Op Ar pattern .Op Ar .Ek @@ -297,6 +298,15 @@ instead of the filename before lines. Force output to be line buffered. By default, output is line buffered when standard output is a terminal and block buffered otherwise. +.It Fl -null +Output a zero byte instead of the character that normally follows a +file name. +This option makes the output unambiguous, even in the presence of file +names containing unusual characters like newlines. +This is similar to the +.Ar -print0 +option in +.Xr find 1 . .El .Sh EXIT STATUS The diff --git a/usr.bin/grep/grep.c b/usr.bin/grep/grep.c index f41b5e20ca6..181af7f6ada 100644 --- a/usr.bin/grep/grep.c +++ b/usr.bin/grep/grep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: grep.c,v 1.65 2020/07/23 20:19:27 martijn Exp $ */ +/* $OpenBSD: grep.c,v 1.66 2022/06/26 10:57:36 op Exp $ */ /*- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav @@ -80,6 +80,7 @@ int vflag; /* -v: only show non-matching lines */ int wflag; /* -w: pattern must start and end on word boundaries */ int xflag; /* -x: pattern must match entire line */ int lbflag; /* --line-buffered */ +int nullflag; /* --null */ const char *labelname; /* --label=name */ int binbehave = BIN_FILE_BIN; @@ -89,6 +90,7 @@ enum { HELP_OPT, MMAP_OPT, LINEBUF_OPT, + NULL_OPT, LABEL_OPT, }; @@ -134,6 +136,7 @@ static const struct option long_options[] = {"mmap", no_argument, NULL, MMAP_OPT}, {"label", required_argument, NULL, LABEL_OPT}, {"line-buffered", no_argument, NULL, LINEBUF_OPT}, + {"null", no_argument, NULL, NULL_OPT}, {"after-context", required_argument, NULL, 'A'}, {"before-context", required_argument, NULL, 'B'}, {"context", optional_argument, NULL, 'C'}, @@ -436,6 +439,9 @@ main(int argc, char *argv[]) case LINEBUF_OPT: lbflag = 1; break; + case NULL_OPT: + nullflag = 1; + break; case HELP_OPT: default: usage(); diff --git a/usr.bin/grep/grep.h b/usr.bin/grep/grep.h index 731bbcc35af..07c8069d5aa 100644 --- a/usr.bin/grep/grep.h +++ b/usr.bin/grep/grep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: grep.h,v 1.28 2021/03/10 21:55:22 millert Exp $ */ +/* $OpenBSD: grep.h,v 1.29 2022/06/26 10:57:36 op Exp $ */ /*- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav @@ -68,7 +68,7 @@ extern int cflags, eflags; extern int Aflag, Bflag, Eflag, Fflag, Hflag, Lflag, Rflag, Zflag, bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag, qflag, - sflag, vflag, wflag, xflag; + sflag, vflag, wflag, xflag, nullflag; extern int binbehave; extern const char *labelname; diff --git a/usr.bin/grep/util.c b/usr.bin/grep/util.c index 33b10946590..d1840b96513 100644 --- a/usr.bin/grep/util.c +++ b/usr.bin/grep/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.65 2022/05/30 16:07:28 dv Exp $ */ +/* $OpenBSD: util.c,v 1.66 2022/06/26 10:57:36 op Exp $ */ /*- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav @@ -172,13 +172,13 @@ procfile(char *fn) if (cflag) { if (!hflag) - printf("%s:", ln.file); + printf("%s%c", ln.file, nullflag ? '\0' : ':'); printf("%llu%s\n", c, overflow ? "+" : ""); } if (lflag && c != 0) - printf("%s\n", fn); + printf("%s%c", fn, nullflag ? '\0' : '\n'); if (Lflag && c == 0) - printf("%s\n", fn); + printf("%s%c", fn, nullflag ? '\0' : '\n'); if (c && !cflag && !lflag && !Lflag && binbehave == BIN_FILE_BIN && nottext && !qflag) printf("Binary file %s matches\n", fn); @@ -653,27 +653,32 @@ grep_revstr(unsigned char *str, int len) void printline(str_t *line, int sep, regmatch_t *pmatch) { - int n; + int n, printsep; n = 0; + printsep = !nullflag; if (!hflag) { fputs(line->file, stdout); + if (nullflag) + putchar(0); ++n; } if (nflag) { - if (n) + if (n && printsep) putchar(sep); printf("%lld", line->line_no); + printsep = 1; ++n; } if (bflag) { - if (n) + if (n && printsep) putchar(sep); printf("%lld", (long long)line->off + (pmatch ? pmatch->rm_so : 0)); + printsep = 1; ++n; } - if (n) + if (n && printsep) putchar(sep); if (pmatch) fwrite(line->dat + pmatch->rm_so, -- 2.20.1