From bc94551f63cfc4c05a56628dfcb386707d9e98cb Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Sat, 26 Sep 2015 14:22:26 +0100 Subject: head,tail: add the -z,--zero-terminated option * doc/coreutils.texi: Reference the option description. * src/head.c: Parameterize the delimiter character. * src/tail.c: Likewise. * tests/misc/head.pl: Add test case. * tests/misc/tail.pl: Likewise. * NEWS: Mention the new feature. --- src/tail.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'src/tail.c') diff --git a/src/tail.c b/src/tail.c index 9007888fc..781adf200 100644 --- a/src/tail.c +++ b/src/tail.c @@ -180,6 +180,9 @@ static bool from_start; /* If true, print filename headers. */ static bool print_headers; +/* Character to split lines by. */ +static char line_end; + /* When to print the filename banners. */ enum header_mode { @@ -238,6 +241,7 @@ static struct option const long_options[] = {"silent", no_argument, NULL, 'q'}, {"sleep-interval", required_argument, NULL, 's'}, {"verbose", no_argument, NULL, 'v'}, + {"zero-terminated", no_argument, NULL, 'z'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0} @@ -296,6 +300,9 @@ With more than one FILE, precede each with a header giving the file name.\n\ with inotify and --pid=P, check process P at\n\ least once every N seconds\n\ -v, --verbose always output headers giving file names\n\ +"), stdout); + fputs (_("\ + -z, --zero-terminated line delimiter is NUL, not newline\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -499,7 +506,7 @@ file_lines (const char *pretty_filename, int fd, uintmax_t n_lines, *read_pos = pos + bytes_read; /* Count the incomplete line on files that don't end with a newline. */ - if (bytes_read && buffer[bytes_read - 1] != '\n') + if (bytes_read && buffer[bytes_read - 1] != line_end) --n_lines; do @@ -510,7 +517,7 @@ file_lines (const char *pretty_filename, int fd, uintmax_t n_lines, while (n) { char const *nl; - nl = memrchr (buffer, '\n', n); + nl = memrchr (buffer, line_end, n); if (nl == NULL) break; n = nl - buffer; @@ -595,7 +602,7 @@ pipe_lines (const char *pretty_filename, int fd, uintmax_t n_lines, { char const *buffer_end = tmp->buffer + n_read; char const *p = tmp->buffer; - while ((p = memchr (p, '\n', buffer_end - p))) + while ((p = memchr (p, line_end, buffer_end - p))) { ++p; ++tmp->nlines; @@ -649,7 +656,7 @@ pipe_lines (const char *pretty_filename, int fd, uintmax_t n_lines, goto free_lbuffers; /* Count the incomplete line on files that don't end with a newline. */ - if (last->buffer[last->nbytes - 1] != '\n') + if (last->buffer[last->nbytes - 1] != line_end) { ++last->nlines; ++total_lines; @@ -671,7 +678,7 @@ pipe_lines (const char *pretty_filename, int fd, uintmax_t n_lines, size_t j; for (j = total_lines - n_lines; j; --j) { - beg = memchr (beg, '\n', buffer_end - beg); + beg = memchr (beg, line_end, buffer_end - beg); assert (beg); ++beg; } @@ -857,7 +864,7 @@ start_lines (const char *pretty_filename, int fd, uintmax_t n_lines, *read_pos += bytes_read; char *p = buffer; - while ((p = memchr (p, '\n', buffer_end - p))) + while ((p = memchr (p, line_end, buffer_end - p))) { ++p; if (--n_lines == 0) @@ -2047,7 +2054,7 @@ parse_options (int argc, char **argv, { int c; - while ((c = getopt_long (argc, argv, "c:n:fFqs:v0123456789", + while ((c = getopt_long (argc, argv, "c:n:fFqs:vz0123456789", long_options, NULL)) != -1) { @@ -2124,6 +2131,10 @@ parse_options (int argc, char **argv, *header_mode = always; break; + case 'z': + line_end = '\0'; + break; + case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); @@ -2221,6 +2232,7 @@ main (int argc, char **argv) count_lines = true; forever = from_start = print_headers = false; + line_end = '\n'; obsolete_option = parse_obsolete_option (argc, argv, &n_units); argc -= obsolete_option; argv += obsolete_option; -- cgit v1.2.3-54-g00ecf