Maintaining file descriptor attributes across execve()

Maintaining file descriptor attributes across execve()

Post by Scott M Sta » Tue, 22 Oct 1991 13:46:39



How can I maintain a file descriptor's attributes across an execve()?
The problem I am having is that when I turn i/o buffering off using
setvbuf() in the child process, buffering ends up being restored in
the exec'd program.  For example, look at the FILE* structures for the
child process before and after the execve():

Before execve():
{
  _cnt = 0;
  _ptr = 0xcef08 "";
  _base = 0xcef08 "";
  _bufsiz = 0;
  _flag = 153;
  _file = 0 '\000';
  _smallbuf = 0 '\000';

Quote:}

After execve():
{
  _cnt = 0;
  _ptr = 0x101ea " child stdin\n";
  _base = 0x101e8 "1\n child stdin\n";
  _bufsiz = 4096;
  _flag = 9;
  _file = 0 '\000';
  _smallbuf = 0 '\000';

Quote:}

The man page for execve() says that open file descriptors are not effected
by the call.  Obviously this is not quite true.

Any ideas on how I can maintain the unbuffered attribute?

Thanks,
Scott Stark

 
 
 

Maintaining file descriptor attributes across execve()

Post by Dave Eis » Tue, 22 Oct 1991 23:24:38



Quote:

>The man page for execve() says that open file descriptors are not effected
>by the call.  Obviously this is not quite true.

It is entirely true. The file descriptor is a small integer index into
a kernel table, both the index and the table are left unchanged by
the exec call. Attributes of this descriptor include things like
whether the file was opened for reading or writing, whether all writes
will be appended to the file or written at the current seek position,
and what this current seek position is. Buffering in the user's data
space is not handled at this level.

Quote:>Any ideas on how I can maintain the unbuffered attribute?

Your problem is that the FILE structure stdio associates with this
descriptor isn't maintained. This FILE is not a kernel structure, it
resides entirely in your program's data space. And yes, since execve
blows away your entire data space, this FILE structure is gone after
the call to exec.

In particular, any setbuf calls you made in the first program will
not be honored by the program you exec. And there ain't a whole lot
you can do about that.

--

      There's something in my library to offend everybody.
        --- Washington Coalition Against Censorship

 
 
 

Maintaining file descriptor attributes across execve()

Post by Guy Harr » Wed, 23 Oct 1991 03:04:00


Quote:>The man page for execve() says that open file descriptors are not effected
>by the call.  Obviously this is not quite true.

No, it *is* true.  What's *not* true is your apparent belief that a
standard I/O stream is a file descriptor.

A standard I/O stream (such as "stdin", "stdout", and "stderr", as
opposed to their underlying file descriptors 0, 1, and 2; note that
"standard input" is not equivalent to "stdin" - "stdin" is just the
standard I/O stream corresponding to the standard input,w hich is file
descriptor 0) - which is what "_cnt", "_ptr", etc.  are properties of -
has, among other things, a file descriptor as an property (that's what
"_file" is), but it has other properties as well.

Standard I/O streams are *NOT* left unaffected by an "exec()"-family
call on most, if not all, flavors of UNIX, because the properties of the
stream are maintained in the process's user-mode address space in the
data area, and the data area gets completely thrown out on an
"exec()"-family call and replaced with a new data area from the
newly-executed program.

Quote:>Any ideas on how I can maintain the unbuffered attribute?

Have the "exec"ed program turn it on when it starts up.
 
 
 

1. execve(), passing file descriptors?

I need to run *part* of standard input through compress, after
inspecting the remainder.  (It's for a weird newsfeed -- boring
details on request.)  While I could pipe it through a subprocess,
that's a rather complicated dance, and I thought there ought to be a
way to pass the properly-positioned file descriptor to compress.  It
sure *looks* as though I should be able to do something like this:

      flags = fcntl(fileno(stdin),F_GETFD);
      flags &= !FD_CLOEXEC;
      fcntl(fileno(stdin),F_SETFD,flags);

      flags = fcntl(fileno(stdout),F_GETFD);
      flags &= !FD_CLOEXEC;
      fcntl(fileno(stdout),F_SETFD,flags);

      if (execlp(DECOMPRESSOR,DECOMPRESSOR,"-d",NULL))
        perror("execlp");

but although compress is launched successfully, it complains about
unexpected end of input.  strace shows the first read() returning
zero.  What did I miss?

(The kernel is Linux 2.2.17, libc is GNU libc 2.2.3 .)

--

Make a good day.

2. Linux VS. NT as gateway for LAN

3. Maintaining .cshrc files across several machines

4. Exabyte VXA packetloader

5. Passing file descriptors across processes

6. users suddenly not in group

7. how to pass a file descriptor across process boundary?

8. The Open Presidency

9. "Bad file descriptor" with Bash; how to designate descriptors?

10. Copying files across file systems

11. moving files across file systems

12. portable way to convert FILE ptr to file descriptor?

13. how to get file length from file descriptor