Jeremie Courreges-Anglas wrote:
> Today someone bumped into a port that contained head -c calls.  While
> upstream could be prodded to care a bit more about portability, support
> for head -c is widespread (GNU coreutils, busybox, FreeBSD, NetBSD) so
> I don't see any value in being different.  Plus, tail(1) already has
> support for -c.
> 
> Comments/ok?

Makes sense and works for me. I'll leave a few comments inline. Also:

> PS: the next diff will remove documentation for the obsolete "-count"
> syntax.

In what sense is it obsolete? I've always used this and I think it's
pretty standard these days. Now that I look, it seems that GNU head(1)
has it but FreeBSD's and NetBSD's don't. I'd be sad to see it go.

> Index: head.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/head/head.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 head.c
> --- head.c    9 Oct 2015 01:37:07 -0000       1.20
> +++ head.c    9 Mar 2016 20:02:08 -0000
> @@ -51,9 +51,9 @@ main(int argc, char *argv[])
>       FILE    *fp;
>       long    cnt;
>       int     ch, firsttime;
> -     long    linecnt = 10;
> +     long    count = 10;

It seems like it'd be better to make this a long long for the sake of
robustness. It's conceivable that someone could try to truncate a file
to a few gigabytes.

>       char    *p = NULL;
> -     int     status = 0;
> +     int     dobytes = 0, status = 0;

I'd definitely prefer stdbool here, but that's contentious.

>  
>       if (pledge("stdio rpath", NULL) == -1)
>               err(1, "pledge");
> @@ -66,13 +66,18 @@ main(int argc, char *argv[])
>               argv++;
>       }
>  
> -     while ((ch = getopt(argc, argv, "n:")) != -1) {
> +     while ((ch = getopt(argc, argv, "c:n:")) != -1) {
>               switch (ch) {
> +             case 'c':
> +                     dobytes = 1;
> +                     p = optarg;
> +                     break;
>               case 'n':
> +                     dobytes = 0;

It's already initialized to 0, which is necessary for the head -count
style syntax.

>                       p = optarg;
>                       break;
>               default:
> -                     usage();        
> +                     usage();

Good catch.

>               }
>       }
>       argc -= optind, argv += optind;
> @@ -80,9 +85,10 @@ main(int argc, char *argv[])
>       if (p) {
>               const char *errstr;
>  
> -             linecnt = strtonum(p, 1, LONG_MAX, &errstr);
> +             count = strtonum(p, 1, LONG_MAX, &errstr);

If using long long, this would have to change too.

>               if (errstr)
> -                     errx(1, "line count %s: %s", errstr, p);
> +                     errx(1, "%s count %s: %s", dobytes ? "bytes" : "lines",
> +                         errstr, p);
>       }
>  
>       for (firsttime = 1; ; firsttime = 0) {
> @@ -105,10 +111,16 @@ main(int argc, char *argv[])
>                       }
>                       ++argv;
>               }
> -             for (cnt = linecnt; cnt && !feof(fp); --cnt)
> -                     while ((ch = getc(fp)) != EOF)
> -                             if (putchar(ch) == '\n')
> -                                     break;
> +             if (dobytes) {
> +                     for (cnt = count; cnt && !feof(fp); --cnt)
> +                             if ((ch = getc(fp)) != EOF)
> +                                     putchar(ch);
> +             } else {
> +                     for (cnt = count; cnt && !feof(fp); --cnt)
> +                             while ((ch = getc(fp)) != EOF)
> +                                     if (putchar(ch) == '\n')
> +                                             break;
> +             }

Total nitpick, but I think switching the for loop condition to "cnt > 0
&& !feof(fp)" would be nice.

>               fclose(fp);
>       }
>       /*NOTREACHED*/

Might as well delete /*NOTREACHED*/

Reply via email to