Sebastian Benoit(be...@openbsd.org) on 2021.01.25 00:27:05 +0100:
> Theo de Raadt(dera...@openbsd.org) on 2021.01.24 16:01:32 -0700:
> > Stuart Henderson <s...@spacehopper.org> wrote:
> > 
> > > On 2021/01/24 12:10, Theo de Raadt wrote:
> > > > I completely despise that the option is called "--null".
> > > > 
> > > > Someone was a complete idiot.
> > > 
> > > gnu grep has both --null and -z for this (why do they do that?!).
> > > If it's added as --null it should be added as -z too.
> > > 
> > > Looking at Debian codesearch most things using it as --null use other
> > > long options that we don't have. Maybe just adding as -z would be
> > > enough. It does seem a useful and fairly widely supported feature.
> > 
> > Yes, maybe just add -z.
> 
> Actually it's "-Z, --null". The lowercase -z in gnu grep is
> 
>        -z, --null-data
>               Treat input and output data as sequences of lines, each
>             terminated by a zero byte (the ASCII NUL character) instead of
>             a newline.  Like the -Z or --null option, this option can be
>             used with commands like sort-z to process arbitrary file
>             names.

And we already have -z for "force grep to behave as zgrep".

Diff below with tedu@ suggestion and changed manpage text.

> 
> Note that we have the -z in sort(1), which at least is consistent.
> That also is a non-posix extension. 
>  
> > > Should have been -0 to match xargs and be similar to find's -print0
> > > but it's too late for that now.
> > 
> > Yes it should have been -0.
> > 
> > But unfortunately some an uneducated idiot got involved.  None of this
> > is standardized.  Unix script portability is being ruined by idiots, not
> > just the people proposing it or writing it originally, but also the people
> > who don't say "wrong" quickly enough.  And much of this is because of
> > intentional development silos.

diff --git usr.bin/grep/grep.1 usr.bin/grep/grep.1
index 5cc228df222..e1edae7e432 100644
--- 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,16 @@ 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 .
+This option is a non-POSIX extension and may not be portable.
 .El
 .Sh EXIT STATUS
 The
diff --git usr.bin/grep/grep.c usr.bin/grep/grep.c
index f41b5e20ca6..279d949fae7 100644
--- 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();
diff --git usr.bin/grep/grep.h usr.bin/grep/grep.h
index b3d24ae662b..37e295d4d40 100644
--- 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;
 
diff --git usr.bin/grep/util.c usr.bin/grep/util.c
index e16d08e7d85..546bd09dc3b 100644
--- 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);
@@ -660,7 +660,7 @@ printline(str_t *line, int sep, regmatch_t *pmatch)
        }
        if (nflag) {
                if (n)
-                       putchar(sep);
+                       putchar(nullflag ? '\0' : sep);
                printf("%lld", line->line_no);
                ++n;
        }

Reply via email to