You know which file descriptors you'd like to do I/O on, but Perl requires filehandles, not descriptor numbers.
To open the file descriptor, use the "<&="
or "<&"
open modes or the IO::Handle module's fdopen
class method:
open(FH, "<&=$FDNUM"); # open FH to the descriptor itself open(FH, "<&$FDNUM"); # open FH to a copy of the descriptor use IO::Handle; $fh->fdopen($FDNUM, "r"); # open file descriptor 3 for reading
To close one by number, either use the POSIX::close
function or else first open it as we did previously.
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 for an already open file descriptor. The "<&"
, ">&"
, and "+<&"
modes to open
will do this for reading, writing, and updating respectively. Adding an equal sign to these to make "<&="
, ">&="
, and "+<&="
is more parsimonious of file descriptors and nearly always what you want to do. That's because it used only a C-level fdopen
function, not a dup2
system call.
If you have version 5.004 or better installed, you can use the IO::Handle object method. This is the same as:
use IO::Handle; $fh = IO::Handle->new(); $fh->fdopen(3, "r"); # open fd 3 for reading
Closing a file descriptor by number is even rarer. The POSIX::close
function does so directly. If your system doesn't have a working POSIX library but does have a working syscall
(and your sysadmin has installed the sys/syscall.ph file created with the h2ph translator), you can call the not very portable syscall
function. It has peculiar parameters and return values: You have to add 0 to numbers and append the empty string (""
) to strings to coerce them to the right types for C, and the error return value is -1 rather than false as in other Perl calls. Needless to say, use syscall
only as a last resort.
Here's how you'd open the 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: $!";
If you want to close a descriptor by number, just open
it first.
The open
function in perlfunc (1) and in Chapter 3 of Programming Perl; the documentation for the standard POSIX and IO::Handle modules (also in Chapter 7 of Programming Perl); your system's fdopen (3) manpages