Book HomePerl CookbookSearch this book

7.19. Opening and Closing File Descriptors by Number

Problem

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

Solution

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.

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 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.

See Also

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


Previous: 7.18. Printing to Many Filehandles SimultaneouslyPerl CookbookNext: 7.20. Copying Filehandles
7.18. Printing to Many Filehandles SimultaneouslyBook Index7.20. Copying Filehandles

Library Navigation Links

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