Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Sep 2001 05:57:56 +0300
From:      Giorgos Keramidas <charon@labs.gr>
To:        Jamie Bowden <ragnar@sysabend.org>
Cc:        chat@FreeBSD.ORG
Subject:   Re: cat(1) strangeness when '-' and options are combined
Message-ID:  <20010908055755.A16153@hades.hell.gr>
In-Reply-To: <Pine.BSF.4.10.10109071914420.41287-100000@moo.sysabend.org>; from ragnar@sysabend.org on Fri, Sep 07, 2001 at 07:16:16PM -0700
References:  <20010908010405.A13448@hades.hell.gr> <Pine.BSF.4.10.10109071914420.41287-100000@moo.sysabend.org>

next in thread | previous in thread | raw e-mail | index | archive | help
From: Jamie Bowden <ragnar@sysabend.org>
Subject: Re: cat(1) strangeness when '-' and options are combined
Date: Fri, Sep 07, 2001 at 07:16:16PM -0700

> On Sat, 8 Sep 2001, Giorgos Keramidas wrote:
> 
> :The manpage of cat(1) says that an argument of '-' is interpreted as
> :the filename of 'stdin'.  The cat(1) source uses getopt() to parse its
> :args, and '-' has a special meaning for getopt too.  This makes cat(1)
> :act in a seemingly strange manner in the following cases:
> :
> :-:- Running cat(1) without *any* command line switches
> :
> :-:- Running cat(1) with similar command line including some switches
> :
> :This is not a bug, since it is the documented way that getopt() works.
> :However, it seems to be somewhat confusing :-(
> :
> :What do the standards-people have to say about this?
> 
> It works exactly as I'd expect it to, see below:
> 
> 7:14pm moo  /home/ragnar %cat -- /etc/fstab
> # Device                Mountpoint      FStype  Options         Dump
> Pass#
> /dev/wd0s1b             none            swap    sw              0       0
> /dev/wd0s1a             /               ufs     rw              1       1
> /dev/wd0s1f             /usr            ufs     rw              2       2
> /dev/wd0s1e             /var            ufs     rw              2       2
> proc                    /proc           procfs  rw              0       0
> 
> Like many utilies, you need the -- because a single - is a valid filename
> in unix.

Nope, there was absolutely no place where I used a 'double' dash.
Please read again what I wrote.

I think you're somehow missing the point I tried to make.  A single
'-' is internally interpreted by the code in src/bin/cat/cat.c as a
valid filename referring to "stdin".

   220                  if (*argv) {
   221                          if (!strcmp(*argv, "-"))
   222                                  fd = fileno(stdin);
   223                          else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
   ...
   228                          }
   229                          filename = *argv++;

That interpretation, however, changes slightly when at least one
switch has been given that starts with '-' because getopt seems to eat
the first '-' and stops at the first command line arg that does /not/
start with '-'.  I was probably unclear in what I said.

If you invoke cat like this:

	% cat - /etc/fstab -

you have to press ^D *twice*.  The first '-' is left intact by
getopt() [probably because it isn't followed by any 'switches'] and
then translated as a reference to "stdin" by cat.  When you press ^D
once, /etc/fstab is printed, and a second '-' is again assumed to be
stdin.  Pressin ^D again stops that too, and the command finishes
successfully.

If at least one option is given to cat though before the first '-',
then cat stops waiting for input from stdin, and upon a *single* press
of ^D /etc/fstab is printed and cat terminates.  A sample of this can
be seen when you try running:

	% cat -n - /etc/fstab -

What I meant to ask (hopefully more clear this time) is: Is this
something that one can rely upon as 'standard' getopt() / cat
behavior.  One of those '-' arguments is interpreted in different ways
depending on whether at least one switch has been passed to cat.

Of course I can always use:

	% cat -n -- - /etc/fstab -

and have the exact same behavior as the first command (plus the extra
feature of having all line snumbered), but the difference in those two
first commands still exists.

I am going to have access to a GNU/Linux box in a few minutes, and
test it there too with their getopt() and cat.

/me hides again, still puzzled

-giorgos


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-chat" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010908055755.A16153>