Re: [hackers] [sbase][PATCH] Support -- in all utilities except echo(1)

From: Laslo Hunhold <dev_AT_frign.de>
Date: Mon, 1 Jul 2019 07:52:22 +0200

On Sun, 30 Jun 2019 21:20:43 -0700
Michael Forney <mforney_AT_mforney.org> wrote:

Dear Michael,

> I'm okay with switching to getopt(3), but also note that the current
> arg.h is probably more complicated than it needs to be. Here's a
> version I rewrote that I've been using in my own projects:
>
> https://git.sr.ht/~mcf/samurai/blob/master/arg.h
>
> I agree that getopt(3) would probably be better at handling the corner
> cases. Yesterday I was planning to check that tools behaved correctly
> with argv = { NULL }. The first thing I tried was rm(1), which tried
> to remove files corresponding to my environment (i.e.
> "SHELL=/bin/ksh"). Yikes!
>
> I am also not sure how getopt(3) could be used to handle the tricky
> cases I mentioned, like printf(1). It doesn't have any options, but
> still needs to support `--` and treat arguments that start with `-` as
> operands rather than printing a usage message.

I fixed the bugs in arg.h a few years ago and use the "fixed version" in
farbfeld and quark (see [0]). Besides the NULL-bug it also allows using
ARGF() more than once in a case and other things. See the commit[1] for
more info.

Glibc requires the environment variable "POSIXLY_CORRECT" to be set to
be fully Posix[2] conformant, but that's just the typical
glibc-insanity. Let's see how a port would look like. A one-to-one
mapping from arg.h to getopt() might be for instance as follows:

        ARGBEGIN {
        case 'a':
                aflag = 1;
                break;
        case 'b':
                bflag = 1;
                break;
        case 'c':
                cflag = 1;
                carg = EARGF(usage());
        default:
                usage();
        } ARGEND

Would be transformed to

        int c;

        while ((c = getopt(argc, argv, "abc:")) != -1) {
                switch (c) {
                case 'a':
                        aflag = 1;
                        break;
                case 'b':
                        bflag = 1;
                        break;
                case 'c':
                        cflag = 1;
                        carg = optarg;
                        break;
                case ':':
                case '?':
                        usage();
                }
        }

Which of the solutions wins this in regard to readability is clear, but
the difference is not too big. The thought of using getopt(3) has
crossed my mind more than once in the past few years. What do the
others think? Is there any big reason speaking against getopt(3)?

With best regards

Laslo

[0]:https://git.suckless.org/farbfeld/file/arg.h.html
[1]:https://git.suckless.org/farbfeld/commit/31651271e1afd99983fb3d0ec51a273e31aaf4e9.html
[2]:https://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html

-- 
Laslo Hunhold <dev_AT_frign.de>

Received on Mon Jul 01 2019 - 07:52:22 CEST

This archive was generated by hypermail 2.3.0 : Mon Jul 01 2019 - 08:00:25 CEST