On 2021-01-22, Omar Polo wrote:
> 
> quasi three-weekly ping.
> 
> Is this such a bad idea?

This seems reasonable. I think there's no need to change print line calls 
though, just patch the implementation once.

> 
> (TBH: I have still to look at how to write a regression test for this)
> 
> Omar Polo <o...@omarpolo.com> writes:
> 
> > Hello,
> >
> > There are various program, especially the one written with GNU grep in
> > mind, that expects various flags that grep in base doesn't have.  While
> > some of the flags (like --color) can be easily worked out (i.e. by
> > patching/customising these programs) one thing that it isn't easily
> > workable is --null, because it alters the way grep outputs its data.
> >
> > --null makes grep output an ASCII NUL byte after the file name, so a
> > program can parse the output of grep unambiguously even when the file
> > names contains "funny" characters, such as a newline.
> >
> > GNU grep isn't the only one with a --null flag, also FreeBSD and NetBSD
> > grep do (at least by looking at their manpages), so it's somewhat
> > widespread.
> >
> > I searched the archives on marc.info but I haven't seen a previous
> > discussion about this.
> >
> > The following patch was tried against GNU grep (installed from packages)
> > and seem to behave consistently.
> >
> > I used the same text of the FreeBSD/NetBSD manpage for the description
> > of the --null option, but I really dislike it: it feels way to verbose
> > for what it's trying to say, but I wasn't able to come up with something
> > better.
> >
> > I'm not familiar at all with the grep codebase, so I hope I'm not
> > missing something.  If this has some chances of being accepted, I guess
> > I should also add some regress test; I'll try to work on them soon, but
> > in the meantime I'm sending this.
> >
> > Thanks,
> >
> > Omar Polo
> 
> 
> diff e992327fc31d0277a6f8518613a7db1b9face78b /home/op/w/openbsd-src
> blob - 5cc228df222c54a0553f289b5da8bbbe6afd171e
> file + usr.bin/grep/grep.1
> --- 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,25 @@ 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 (the ASCII NUL character) instead of the character
> +that normally follows a file name.
> +For example,
> +.Nm Fl l Fl -null
> +outputs a zero byte after each file name instead of the usual newline.
> +This option makes the output unambiguous, even in the presence of file
> +names containing unusual characters like newlines.
> +This option can be used with commands like
> +.Xr find 1
> +.Fl print0 Ns ,
> +.Xr perl 1
> +.Fl 0 Ns ,
> +.Xr sort 1
> +.Fl z Ns , and
> +.Xr args 1
> +.Fl 0
> +to process arbitrary file names, even those that contain newline
> +characters.
>  .El
>  .Sh EXIT STATUS
>  The
> blob - f41b5e20ca68c9e9a36d2f7dd3c44329c621f29b
> file + usr.bin/grep/grep.c
> --- 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 - b3d24ae662beb72c5632190c5c819bcc92f0389a
> file + usr.bin/grep/grep.h
> --- 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 - e16d08e7d859609c2ccbc0ac4bba670188f81abf
> file + usr.bin/grep/util.c
> --- 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);
> @@ -266,9 +266,9 @@ print:
>                       if (Bflag > 0)
>                               printqueue();
>                       linesqueued = 0;
> -                     printline(l, ':', oflag ? &pmatch : NULL);
> +                     printline(l, nullflag ? '\0' : ':', oflag ? &pmatch : 
> NULL);
>               } else {
> -                     printline(l, '-', oflag ? &pmatch : NULL);
> +                     printline(l, nullflag ? '\0' : '-', oflag ? &pmatch : 
> NULL);
>                       tail--;
>               }
>       }
> @@ -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