[hackers] [sbase] tail: Process bytes with -c option, and add -m option for runes || Michael Forney

From: <git_AT_suckless.org>
Date: Fri, 14 Jul 2017 07:51:01 +0200 (CEST)

commit ea8622a4ce21e414050e116542cb76581d40d27a
Author: Michael Forney <mforney_AT_mforney.org>
AuthorDate: Mon Jul 3 14:58:52 2017 -0700
Commit: Anselm R Garbe <garbeam_AT_gmail.com>
CommitDate: Fri Jul 14 07:50:54 2017 +0200

    tail: Process bytes with -c option, and add -m option for runes
    
    POSIX says that -c specifies a number of bytes, not characters. This
    flag is commonly used by scripts that operate on binary files to things
    like extract a header. Treating the offsets as character offsets will
    break things in mysterious ways.
    
    Instead, add a -m option (chosen to match `wc -m`, which also operates
    on characters) to handle character offsets.

diff --git a/tail.1 b/tail.1
index 433404d..281560d 100644
--- a/tail.1
+++ b/tail.1
_AT_@ -7,7 +7,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl f
-.Op Fl c Ar num | Fl n Ar num | Fl Ns Ar num
+.Op Fl c Ar num | Fl m Ar num | Fl n Ar num | Fl Ns Ar num
 .Op Ar file ...
 .Sh DESCRIPTION
 .Nm
_AT_@ -20,10 +20,10 @@ is given,
 reads from stdin.
 .Sh OPTIONS
 .Bl -tag -width Ds
-.It Fl c Ar num | Fl n Ar num | Fl Ns Ar num
+.It Fl c Ar num | Fl m Ar num | Fl n Ar num | Fl Ns Ar num
 Display final
 .Ar num
-characters | lines |
+bytes | characters | lines |
 lines. If
 .Ar num
 begins with '+'
diff --git a/tail.c b/tail.c
index ce65a01..ce3be9d 100644
--- a/tail.c
+++ b/tail.c
_AT_@ -26,12 +26,23 @@ dropinit(int fd, const char *fname, size_t count)
                 goto copy;
         count--; /* numbering starts at 1 */
         while (count && (n = read(fd, buf, sizeof(buf))) > 0) {
- if (mode == 'n') {
+ switch (mode) {
+ case 'n': /* lines */
                         for (p = buf; count && n > 0; p++, n--) {
                                 if (*p == '\n')
                                         count--;
                         }
- } else {
+ break;
+ case 'c': /* bytes */
+ if (count > n) {
+ count -= n;
+ } else {
+ p = buf + count;
+ n -= count;
+ count = 0;
+ }
+ break;
+ case 'm': /* runes */
                         for (p = buf; count && n > 0; p += nr, n -= nr, count--) {
                                 nr = charntorune(&r, p, n);
                                 if (!nr) {
_AT_@ -42,6 +53,7 @@ dropinit(int fd, const char *fname, size_t count)
                                         break;
                                 }
                         }
+ break;
                 }
         }
         if (count) {
_AT_@ -90,7 +102,8 @@ taketail(int fd, const char *fname, size_t count)
                 if (n == 0)
                         break;
                 len += n;
- if (mode == 'n') {
+ switch (mode) {
+ case 'n': /* lines */
                         /* ignore the last character; if it is a newline, it
                          * ends the last line */
                         for (p = buf + len - 2, left = count; p >= buf; p--) {
_AT_@ -102,7 +115,11 @@ taketail(int fd, const char *fname, size_t count)
                                         break;
                                 }
                         }
- } else {
+ break;
+ case 'c': /* bytes */
+ p = count < len ? buf + len - count : buf;
+ break;
+ case 'm': /* runes */
                         for (p = buf + len - 1, left = count; p >= buf; p--) {
                                 /* skip utf-8 continuation bytes */
                                 if ((*p & 0xc0) == 0x80)
_AT_@ -111,6 +128,7 @@ taketail(int fd, const char *fname, size_t count)
                                 if (!left)
                                         break;
                         }
+ break;
                 }
                 if (p > buf) {
                         len -= p - buf;
_AT_@ -125,7 +143,7 @@ taketail(int fd, const char *fname, size_t count)
 static void
 usage(void)
 {
- eprintf("usage: %s [-f] [-c num | -n num | -num] [file ...]\n", argv0);
+ eprintf("usage: %s [-f] [-c num | -m num | -n num | -num] [file ...]\n", argv0);
 }
 
 int
_AT_@ -143,6 +161,7 @@ main(int argc, char *argv[])
                 fflag = 1;
                 break;
         case 'c':
+ case 'm':
         case 'n':
                 mode = ARGC();
                 numstr = EARGF(usage());
Received on Fri Jul 14 2017 - 07:51:01 CEST

This archive was generated by hypermail 2.3.0 : Fri Jul 14 2017 - 08:01:29 CEST