Omar Polo <[email protected]> wrote:
> friendly ping :)
>
> Omar Polo <[email protected]> wrote:
> > Hello everyone,
> >
> > one year ago there was a thread for grep --null [0] and there seemed to
> > be a general agreement (in the diff, not only in how wrong the name
> > --null feels.) In the end it wasn't committed, I got distracted and
> > continued to happily using my patched ~/bin/grep
> >
> > [0]: https://marc.info/?l=openbsd-tech&m=160975008513761&w=2
> >
> > The attached diff was tweaked by benno@ (also after some comments from
> > tedu@) and now i've just fixed an issue in printline which reminded me
> > that this is still pending.
> >
> > (we need to print the NUL byte after the filename and skip the next
> > separator if we want to follow the GNU grep behavior: freebsd' grep does
> > this, netbsd by glancing at the code doesn't.)
> >
> > One thing that wasn't clear in the other thread is the choice of the
> > flag: GNU grep has "-Z, --null" and "-z, --null-data" while our grep has
> > -Z to force it to behave as zgrep and no -z. We also can't use -0
> > because it stands for "print 0 lines of context" (both in GNU grep and
> > ours grep); while it's unlikely that someone is relying on it, it
> > currently "works" and dumping NULs into some pipeline not prepared for
> > them is not sensible. (e.g. a script that does `| grep -$n'...)
> >
> > ok?
updated diff with the sentence about POSIX compatibility in the manpage
dropped as it's already covered by the STANDARDS section. (thanks
deraadt for noticing)
diff 6fc56b85371a32a491ae5a11b5a2e42ebb6d643d
89d6f3bd585a6c57e08206cc8d18a80f18b70a1e
commit - 6fc56b85371a32a491ae5a11b5a2e42ebb6d643d
commit + 89d6f3bd585a6c57e08206cc8d18a80f18b70a1e
blob - 5cc228df222c54a0553f289b5da8bbbe6afd171e
blob + 5b7db2ac9116d097b92c47b7499d40bffa86198b
--- usr.bin/grep/grep.1
+++ usr.bin/grep/grep.1
@@ -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, making the output
+suitable for use with the
+.Fl 0
+option to
+.Xr xargs 1 .
.El
.Sh EXIT STATUS
The
blob - f41b5e20ca68c9e9a36d2f7dd3c44329c621f29b
blob + 279d949fae764262a350e66ce1c21a6864284eb6
--- usr.bin/grep/grep.c
+++ usr.bin/grep/grep.c
@@ -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();
blob - 731bbcc35af4cbf870aaf70ce9913e375142d4d8
blob + 16a1e94a0bcf58498dd4df8d6c7692f1ffdb8045
--- usr.bin/grep/grep.h
+++ usr.bin/grep/grep.h
@@ -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;
blob - 33b1094659071e59c719151bc5d0a247ea3cad23
blob + 9aa0a8b5be2fba7f907dd1d065de692a3407e2f7
--- usr.bin/grep/util.c
+++ usr.bin/grep/util.c
@@ -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,