SJS wrote:
begin quoting Ralph Shumaker as of Sat, Mar 29, 2008 at 09:55:37AM -0700:
[snip]
I don't know what programming or scripting language we're talking about
here. Let's just say that I am almost completely unfamiliar with what
scripting or programming language is needed for stdin, stdout, and
stderr. I think someone said stdin is 0, stdout is 1, stderr is 2, and
more numbers are available, but with no standard names. Stewart
suggested possibly petitioning POSIX for a label of stdstatus, let's
assume they agree and make that 3.
Could someone please show me, as simply as possible, an example script
or program that uses each of these? I don't know enough about it to
envision it.
-----------------------------------------------------------------------------
#!/bin/psuedoscript
#
# Find all of the files with copyright notices
foreach f in $( find . -type f -iname '*.jpg' ) do
print -stdstatus "Processing file $f"
if ( ! -r $f ) then
print -stderr "Cannot read file $f"
fi
readjpgcmt $f | grep -i "copyright"
if ( $status ) then
print -stdout "$f"
fi
rof
-----------------------------------------------------------------------------
I actually felt excitement when I saw the code, thinking, "I may finally
understand this well enough to retain it.".
The only thing I don't see in your example is an explicit "stdin". Is
that one ever used explicitly, like you just did above with the other three?
In the example above, what things I did not know, I was able to figure
out from the context of the rest (for example, the "! -r $f" was unclear
to me until the next line of code).
And just for grins, let's say the author wants more output channels for
whatever reason. Would he likely choose higher numbers than the next
available numbers (just in case POSIX later decides to add more
stdxxx)? Or would he likely use the next numbers available since stdin,
stdout, and stderr have been the only ones for many many many years?
Bourne shell apparently allows this.
Consider:
-----------------------------------------------------------------------------
$ cat fdtest.c
#include <stdlib.h>
#include <stdio.h>
int main( int argc, char **argv ) {
FILE *stdstatus;
fprintf( stdout, "stdout\n");
fprintf( stderr, "stderror\n");
stdstatus = fdopen( 3, "w" );
if ( stdstatus == NULL ) {
if ( argc > 1 ) fprintf( stderr, "Can't open file descriptor
#3\n");
return EXIT_FAILURE;
}
fprintf( stdstatus, "stdstatus\n");
return EXIT_SUCCESS;
}
$
-----------------------------------------------------------------------------
I'm guessing this "fdtest.c" is a made-up example? (I don't find it in
my fc7.) If so, are you saying that an individual can assign his own
choice of terms to open channels? Is that what you did above for channel 3?
The code looks like C (tho I am unfamiliar enough with other languages
to be able to distinguish it) and the ".c" seems to confirm that.
Just for the sake of helping me to be able to follow better in the code
above, please explain the line:
int main( int argc, char **argv ) {
I don't know C very well at all. I think "main( ... )" is the title of
the "{ ... }" code that follows (perl taught me that). I don't know the
terms "int", "argc", "char", "**argv", or why the double asterisk
precedes "argv".
Also, please explain the next line, namely:
FILE *stdstatus;
Why the single asterisk preceding "stdstatus"? Other than that, I
assume that this line is an instruction to create a "file" (all in *nix
is a file) called "stdstatus" and that the line(s) following (in the
block) describe aspects about what kind of file it is as well as
handling the error if not being able to open it the way you expect it to
work. But if that's the case, I don't understand why the following two
lines seem to be part of that process:
fprintf( stdout, "stdout\n");
fprintf( stderr, "stderror\n");
Perhaps "FILE *stdstatus" _could_ be placed just prior to the "stdstatus
= ..." line, but coding etiquette places it at the beginning of the
block? And perhaps the "stdstatus = ..." and "if ( ... ) { ... } could
be placed right after the "FILE *stdstatus" line, but maybe scalability
and readability argue that it should be placed just prior to its debut?
I think I spelled out most of what I don't understand about the code
above. Oh, one more thing:
stdstatus = fdopen( 3, "w" )
I assume fdopen is file-descriptor-open, and 3 being the next available
number (after 0=stdin, 1=stdout, and 2=stderror). I don't get the
'"w"'. "man fdopen" (more confusing than not) explains the 'w' option
but it doesn't help me to understand it. Although, reading the other
options help me to understand this one better. This option is only for
writing out, and wipes out any previous content in '3', yes?
I think I understand the rest of it (partly because of the behavior of
it in the examples below, and partly for similarities to other languages).
Let's say that a user invokes that program. What will he see?
Let's say that a user invokes that program with simple redirection to a
file. What will he see?
-----------------------------------------------------------------------------
lancre> !gcc
gcc -o fdtest fdtest.c
You just compiled fdtest.c into fdtest?
lancre> ./fdtest
stdout
stderror
lancre> ./fdtest -v
stdout
stderror
Can't open file descriptor #3
I don't know what is "lancre>" (other than a possible reference to "Ever
After"), but it appears that the "stdstatus" assignment to 3 failed in
that environment?
lancre> sh
Entering into an "sh" shell (close enough to bash for me to follow).
$ ./fdtest
stdout
stderror
$ ./fdtest -v 3>&1
stdout
stderror
stdstatus
So if cdparanoia had status messages going to 3 (stdstatus), and
defaults to "-v 3>&2", and --quiet changes it such that 3>/dev/null,
then Lan will be happy if he uses --quiet? ;) Anybody know if
cdparanoia puts status messages out directly on channel 2 or just
redirects whatever channel it uses for status messages to show up on 2?
$ ./fdtest -v 3>&1 1>out.1 2>out.2
stdstatus
$ cat out.1
stdout
$ cat out.2
stderror
$
-----------------------------------------------------------------------------
Amazingly, I actually followed all that. Thanks.
I've had limited experience with this when I did "du -a > ~/du-a" and
got what I assume is stdout in the file but what I assume is stderr
still on the screen. It seems like, without redirection, both stdout
and stderr outputs went to screen, but redirection split them. Is this
observation correct?
Yup.
I've seen fancy ~"> 2&"~ or whatnot (couldn't quote it accurately from
memory since I never really understood it). Is there some resource that
could explain such things, preferably simple explanations designed for
total NOOBS?
1, 2, 3, etc. are file descriptors.
So, in coding, you use the terms stdin, stdout, stderr, and (our
proposed POSIX-adopted) stdstatus, but on the command line you use 0, 1,
2, and 3 respectively, yes?
#>filename will redirect file descriptor # to the file filename
The file &# is special -- that's a target file descriptor, so when
you see A>&B (in a bourne shell), where A and B are numbers, that's
saying "point A to wherever B is right now".
-----------------------------------------------------------------------------
$ ./fdtest > out.1 2>&1
$ ./fdtest 2>&1 > out.2
stderror
So each one is successive. Each one builds upon the previous.
$ cat out.1
stderror
stdout
Why did stderror appear _before_ stdout? I expected the reverse sequence.
$ cat out.2
stdout
$
-----------------------------------------------------------------------------
If you really wanted to, you could swap stdout and stderr...
-----------------------------------------------------------------------------
$ ./fdtest
stdout
stderror
$ ./fdtest > /dev/null
stderror
$ ./fdtest 2> /dev/null
stdout
$ ./fdtest > /dev/null 2>&1
$ ./fdtest 3>&1 1>&2 2>&3 > /dev/null
stderror
stdstatus
$
-----------------------------------------------------------------------------
I totally followed it until the last one. On the last one, I expect the
opposite result. I expect "stderror" and "stdstatus" to end up in
/dev/null and "stdout" to be the only one showing up on the screen.
What did I miss?
Here's how I see it (correct me where I go wrong):
$ ./fdtest 3>&1 (3 jumps out of stdstatus' bed and into bed with 1 in
stdout's bed)
$ ./fdtest 3>&1 1>&2 (1 jumps out of stdout's bed and into bed with 2 in
stderr's bed)
$ ./fdtest 3>&1 1>&2 2>&3 (2 jumps out of stderr's bed and into bed with
3 (currently in stdout's bed - even though 1 is now in stderr's bed)
$ ./fdtest 3>&1 1>&2 2>&3 > /dev/null (dumps stdout's bed (with current
occupants 3 and 2) into /dev/null and outputs stderr's bed (with current
occupant 1) to screen)
--
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-list