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>
