This thread was almost about Python once

Clarence Gardner clarence at beach.silcom.com
Tue Feb 1 10:29:40 EST 2000


Clarence Gardner <clarence at beach.silcom.com> wrote:
: What interpreter is so braindead as to assume that particular file
: descriptors are available when it is invoked?  And even if there are
: any, catering to them is worse than all of the Microsoft backward-
: compatibility-to-1985 hacks put together, IMNSHO.

To which Ivan Van Laningham <ivan at callware.com> replied:
>stdin = fd 0
>stdout = fd 1
>stderr = fd2
>next fd you ask for = fd3
>Not braindead at all.  Just a nice tradition, which is observed on
>unices & their descendents, but not on M$.

and Fredrik Lundh mentioned the Single Unix Specification
>    At program startup, three streams are predefined and need
>    not be opened explicitly: standard input (for reading conventional
>    input), standard output (for writing conventional output), and
>    standard error (for writing diagnostic output). 
>    The following symbolic constants are defined for file streams: 
>    STDIN_FILENO
>    File number of stdin. It is 0. 
>    STDOUT_FILENO
>    File number of stdout. It is 1. 
>    STDERR_FILENO
>    File number of stderr. It is 2. 

What I said was braindead was the assumption of the file descriptor
state.  Sure, if fds 0,1,2 are open, *and no others are*, then the next
file you open will be on fd 3.  That is more than a Unix tradition, it
is an absolute requirement for any Unix kernel.  That is, after all, why
most often the file descriptor that the script text is open on would be 3.
But there is no reason in the world to require that fd 3 was not already
open to something else.  (My use of /dev/fd/6 as an example in my
original message was not to say that the fd will be arbitrary, but it
can be unknowable in advance.)

The part of the SUS that /F quotes (I haven't read it) sounds like it is
talking about C (certainly the symbolic constants are), and to be picky,
which one must when referring to specifications, that neither says that
no other fds (not streams, which is a C issue) will be open, but it
doesn't even require that fds 0, 1, or 2 be open.  If, for whatever
reason, fd 1 was not open when your program started, stdout would still
be properly defined and initialized in your program -- you would just
get an error if you tried to write to it.  This is, of course, unusual.
But the spec can hardly guarantee the state that your program starts in.
It cannot guarantee that it was not started by this program:
   #include <unistd.h>
   #include <fcntl.h>
   int main(void)
   {   int three = open("/", "rb");
       fcntl(three, F_SETFD, 0);
       close(1);
       execl("/yourprogram", 0);
   }

And similarly, to get back to the issue (and to the reasonable world:) ),
there is nothing at all wrong with running a setuid script like this:
   $ setuidscript 3</etc/passwd
which, even in a perfectly normal environment with a perfectly normal shell,
will (on the safe systems under discussion) deliver the script text to the
interpreter on file descriptor 4.

-- 
Clarence Gardner
Software Engineer
NetLojix Communications    NASDAQ:NETX
clarence at netlojix.com



More information about the Python-list mailing list