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

Reply via email to