Opening and Closing File Descriptors by Number (Perl Cookbook, 2nd Edition)

## 7.9. Opening and Closing File Descriptors by Number

### 7.9.1. Problem

You know which file descriptors you'd like to do I/O on, but Perl requires filehandles, not descriptor numbers.

### 7.9.2. Solution

To open the file descriptor, supply `open` with "`<&=`" or "`<&`" as the part of the file access mode, combined with a directional arrow:

>     open(FH, "<&=", $FDNUM)       # open FH to the descriptor itself
>     open(FH, "<&",  $FDNUM);      # open FH to a copy of the descriptor

Or use the IO::Handle module's `new_from_fd` class method:

>     use IO::Handle;
>     $fh = IO::Handle->new_from_fd($FDNUM, "r");

To close a file descriptor by number, either use the `POSIX::close` function or open it first as shown previously.

### 7.9.3. Discussion

Occasionally you have a file descriptor but no filehandle. Perl's I/O system uses filehandles instead of file descriptors, so you have to make a new filehandle from an already open file descriptor. The "`<&`", "`>&`", and "`+<&`" access modes to `open` do this for reading, writing, and updating, respectively. Adding an equals sign to these—making them "`<&=`", "`>&=`", and "`+<&=`"—is more parsimonious of file descriptors and nearly always what you want. That's because the underlying implementation of Perl's `open` statement uses only a C-level fdopen(3) function from the C library, not a dup2(2) syscall that calls the kernel.

The `new_from_fd` IO::Handle object method is equivalent to:

>     use IO::Handle;

>     $fh = new IO::Handle;
>     $fh->fdopen($FDNUM, "r");            # open fd 3 for reading

Here's how you'd open file descriptors that the MH mail system feeds its child processes. It identifies them in the environment variable `MHCONTEXTFD`:

>     $fd = $ENV{MHCONTEXTFD};
>     open(MHCONTEXT, "<&=", $fd)   or die "couldn't fdopen $fd: $!";
>     # after processing
>     close(MHCONTEXT)              or die "couldn't close context file: $!";

Closing a file descriptor by number is even rarer. If you've already opened a filehandle for the file descriptor you want to close, simply use Perl's `close` function on the filehandle. If don't have a filehandle for that file descriptor, the `POSIX::close` function closes a file descriptor by number:

>     use POSIX;

>     POSIX::close(3);              # close fd 3

### 7.9.4. See Also

The `open` function in perlfunc(1) and in Chapter 29 of Programming Perl; the documentation for the standard POSIX and IO::Handle modules (also in Chapter 32 of Programming Perl); your system's fdopen(3) manpages

Copyright © 2003 O'Reilly & Associates. All rights reserved.