Add test for grep() and wantarray
[p5sagit/p5-mst-13.2.git] / pod / perlipc.pod
index 3166f1a..83f3d4b 100644 (file)
@@ -1,7 +1,6 @@
 =head1 NAME
 
-perlipc - Perl interprocess communication (signals, fifos, pipes, safe
-subprocceses, sockets, and semaphores)
+perlipc - Perl interprocess communication (signals, fifos, pipes, safe subprocesses, sockets, and semaphores)
 
 =head1 DESCRIPTION
 
@@ -15,13 +14,13 @@ Perl uses a simple signal handling model: the %SIG hash contains names or
 references of user-installed signal handlers.  These handlers will be called
 with an argument which is the name of the signal that triggered it.  A
 signal may be generated intentionally from a particular keyboard sequence like
-control-C or control-Z, sent to you from an another process, or
+control-C or control-Z, sent to you from another process, or
 triggered automatically by the kernel when special events transpire, like
 a child process exiting, your process running out of stack space, or 
 hitting file size limit.
 
 For example, to trap an interrupt signal, set up a handler like this.
-Notice how all we do is set with a global variable and then raise an
+Notice how all we do is set a global variable and then raise an
 exception.  That's because on most systems libraries are not
 re-entrant, so calling any print() functions (or even anything that needs to
 malloc(3) more memory) could in theory trigger a memory fault
@@ -48,7 +47,7 @@ indexed by name to get the number:
        $i++;
     }   
 
-So to check whether signal 17 and SIGALRM were the same, just do this:
+So to check whether signal 17 and SIGALRM were the same, do just this:
 
     print "signal #17 = $signame[17]\n";
     if ($signo{ALRM}) { 
@@ -97,28 +96,30 @@ handlers:
 
 But that will be problematic for the more complicated handlers that need
 to re-install themselves.  Because Perl's signal mechanism is currently
-based on the signal(3) function from the C library, you may somtimes be so
+based on the signal(3) function from the C library, you may sometimes be so
 misfortunate as to run on systems where that function is "broken", that
 is, it behaves in the old unreliable SysV way rather than the newer, more
 reasonable BSD and POSIX fashion.  So you'll see defensive people writing
 signal handlers like this:
 
     sub REAPER { 
-       $SIG{CHLD} = \&REAPER;  # loathe sysV
        $waitedpid = wait;
+       # loathe sysV: it makes us not only reinstate
+       # the handler, but place it after the wait
+       $SIG{CHLD} = \&REAPER;  
     }
     $SIG{CHLD} = \&REAPER;
     # now do something that forks...
 
 or even the more elaborate:
 
-    use POSIX "wait_h";
+    use POSIX ":sys_wait_h";
     sub REAPER { 
        my $child;
-       $SIG{CHLD} = \&REAPER;  # loathe sysV
         while ($child = waitpid(-1,WNOHANG)) {
            $Kid_Status{$child} = $?;
        } 
+       $SIG{CHLD} = \&REAPER;  # still loathe sysV
     }
     $SIG{CHLD} = \&REAPER;
     # do something that forks...
@@ -172,9 +173,9 @@ on the other end.
 
 For example, let's say you'd like to have your F<.signature> file be a
 named pipe that has a Perl program on the other end.  Now every time any
-program (like a mailer, newsreader, finger program, etc.) tries to read
+program (like a mailer, news reader, finger program, etc.) tries to read
 from that file, the reading program will block and your program will
-supply the the new signature.  We'll use the pipe-checking file test B<-p>
+supply the new signature.  We'll use the pipe-checking file test B<-p>
 to find out whether anyone (or anything) has accidentally removed our fifo.
 
     chdir; # go home
@@ -192,7 +193,7 @@ to find out whether anyone (or anything) has accidentally removed our fifo.
        open (FIFO, "> $FIFO") || die "can't write $FIFO: $!";
        print FIFO "John Smith (smith\@host.org)\n", `fortune -s`;
        close FIFO;
-       sleep 2;    # to avoid dup sigs
+       sleep 2;    # to avoid dup signals
     }
 
 
@@ -200,7 +201,7 @@ to find out whether anyone (or anything) has accidentally removed our fifo.
 
 Perl's basic open() statement can also be used for unidirectional interprocess
 communication by either appending or prepending a pipe symbol to the second
-argument to open().  Here's how to start something up a child process you
+argument to open().  Here's how to start something up in a child process you
 intend to write to:
 
     open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") 
@@ -217,7 +218,7 @@ And here's how to start up a child process you intend to read from:
        next if /^(tcp|udp)/;
        print;
     } 
-    close SPOOLER || die "bad netstat: $! $?";
+    close STATUS || die "bad netstat: $! $?";
 
 If one can be sure that a particular program is a Perl script that is
 expecting filenames in @ARGV, the clever programmer can write something
@@ -230,7 +231,7 @@ read from the file F<f1>, the process F<cmd1>, standard input (F<tmpfile>
 in this case), the F<f2> file, the F<cmd2> command, and finally the F<f3>
 file.  Pretty nifty, eh?
 
-You might notice that you could use backticks for much the
+You might notice that you could use back-ticks for much the
 same effect as opening a pipe for reading:
 
     print grep { !/^(tcp|udp)/ } `netstat -an 2>&1`;
@@ -249,7 +250,7 @@ exist: the open() will in all likelihood succeed (it only reflects the
 fork()'s success), but then your output will fail--spectacularly.  Perl
 can't know whether the command worked because your command is actually
 running in a separate process whose exec() might have failed.  Therefore,
-while readers of bogus commands just return a quick end of file, writers
+while readers of bogus commands return just a quick end of file, writers
 to bogus command will trigger a signal they'd better be prepared to
 handle.  Consider:
 
@@ -274,7 +275,7 @@ you opened whatever your kid writes to his STDOUT.
     my $sleep_count = 0;
 
     do { 
-       $pid = open(KID, "-|");
+       $pid = open(KID_TO_WRITE, "|-");
        unless (defined $pid) {
            warn "cannot fork: $!";
            die "bailing out" if $sleep_count++ > 6;
@@ -283,8 +284,8 @@ you opened whatever your kid writes to his STDOUT.
     } until defined $pid;
 
     if ($pid) {  # parent
-       print KID @some_data;
-       close(KID) || warn "kid exited $?";
+       print KID_TO_WRITE @some_data;
+       close(KID_TO_WRITE) || warn "kid exited $?";
     } else {     # child
        ($EUID, $EGID) = ($UID, $GID); # suid progs only
        open (FILE, "> /safe/file") 
@@ -297,20 +298,20 @@ you opened whatever your kid writes to his STDOUT.
 
 Another common use for this construct is when you need to execute
 something without the shell's interference.  With system(), it's
-straigh-forward, but you can't use a pipe open or backticks safely.
+straightforward, but you can't use a pipe open or back-ticks safely.
 That's because there's no way to stop the shell from getting its hands on
 your arguments.   Instead, use lower-level control to call exec() directly.
 
-Here's a safe backtick or pipe open for read:
+Here's a safe back-tick or pipe open for read:
 
     # add error processing as above
-    $pid = open(KID, "-|");
+    $pid = open(KID_TO_READ, "-|");
 
     if ($pid) {   # parent
-       while (<KID>) {
+       while (<KID_TO_READ>) {
            # do something interesting
        }         
-       close(KID) || warn "kid exited $?";
+       close(KID_TO_READ) || warn "kid exited $?";
 
     } else {      # child
        ($EUID, $EGID) = ($UID, $GID); # suid only
@@ -323,14 +324,14 @@ Here's a safe backtick or pipe open for read:
 And here's a safe pipe open for writing:
 
     # add error processing as above
-    $pid = open(KID, "|-");
+    $pid = open(KID_TO_WRITE, "|-");
     $SIG{ALRM} = sub { die "whoops, $program pipe broke" };
 
     if ($pid) {  # parent
        for (@data) {
-           print KID;
+           print KID_TO_WRITE;
        } 
-       close(KID) || warn "kid exited $?";
+       close(KID_TO_WRITE) || warn "kid exited $?";
 
     } else {     # child
        ($EUID, $EGID) = ($UID, $GID);
@@ -341,8 +342,8 @@ And here's a safe pipe open for writing:
 
 Note that these operations are full Unix forks, which means they may not be
 correctly implemented on alien systems.  Additionally, these are not true
-multithreading.  If you'd like to learn more about threading, see the
-F<modules> file mentioned below in the L<SEE ALSO> section.
+multi-threading.  If you'd like to learn more about threading, see the
+F<modules> file mentioned below in the SEE ALSO section.
 
 =head2 Bidirectional Communication
 
@@ -350,15 +351,15 @@ While this works reasonably well for unidirectional communication, what
 about bidirectional communication?  The obvious thing you'd like to do
 doesn't actually work:
 
-    open(KID, "| some program |")
+    open(PROG_FOR_READING_AND_WRITING, "| some program |")
 
-and if you forgot to use the B<-w> flag, then you'll miss out 
+and if you forget to use the B<-w> flag, then you'll miss out 
 entirely on the diagnostic message:
 
     Can't do bidirectional pipe at -e line 1.
 
 If you really want to, you can use the standard open2() library function
-to catch both ends.  There's also an open3() for tridirectional I/O so you
+to catch both ends.  There's also an open3() for tri-directional I/O so you
 can also catch your child's STDERR, but doing so would then require an
 awkward select() loop and wouldn't allow you to use normal Perl input
 operations.
@@ -379,10 +380,10 @@ Here's an example of using open2():
     print Writer "stuff\n";
     $got = <Reader>;
 
-The problem with this is that Unix buffering is going to really
-ruin your day.  Even though your C<Writer> filehandle is autoflushed,
+The problem with this is that Unix buffering is really going to
+ruin your day.  Even though your C<Writer> filehandle is auto-flushed,
 and the process on the other end will get your data in a timely manner,
-you can't usually do anything to force it to actually give it back to you
+you can't usually do anything to force it to give it back to you
 in a similarly quick fashion.  In this case, we could, because we 
 gave I<cat> a B<-u> flag to make it unbuffered.  But very few Unix
 commands are designed to operate over pipes, so this seldom works
@@ -401,17 +402,17 @@ pseudo-ttys to make your program behave more reasonably:
 
 This way you don't have to have control over the source code of the
 program you're using.  The F<Comm> library also has expect() 
-and interact() functions.  Find the library (and hopefully its 
+and interact() functions.  Find the library (and we hope its 
 successor F<IPC::Chat>) at your nearest CPAN archive as detailed
-in the L<SEE ALSO> section below.
+in the SEE ALSO section below.
 
 =head1 Sockets: Client/Server Communication
 
-While not limited to Unix-derived operating systems (e.g. WinSock on PCs
+While not limited to Unix-derived operating systems (e.g., WinSock on PCs
 provides socket support, as do some VMS libraries), you may not have
-sockets on your system, in which this section probably isn't going to do
-you much good.  With sockets, you can do both virtual circuits (i.e. TCP
-streams) and datagrams (i.e. UDP packets).  You may be able to do even more
+sockets on your system, in which case this section probably isn't going to do
+you much good.  With sockets, you can do both virtual circuits (i.e., TCP
+streams) and datagrams (i.e., UDP packets).  You may be able to do even more
 depending on your system.
 
 The Perl function calls for dealing with sockets have the same names as
@@ -459,7 +460,52 @@ Here's a sample TCP client using Internet-domain sockets:
 
 And here's a corresponding server to go along with it.  We'll
 leave the address as INADDR_ANY so that the kernel can choose
-the appropriate interface on multihomed hosts:
+the appropriate interface on multi-homed hosts.  If you want sit
+on a particular interface (like the external side of a gateway
+or firewall machine), you should fill this in with your real address
+instead.
+
+    #!/usr/bin/perl -Tw
+    require 5.002;
+    use strict;
+    BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
+    use Socket;
+    use Carp;
+
+    sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" } 
+
+    my $port = shift || 2345;
+    my $proto = getprotobyname('tcp');
+    $port = $1 if $port =~ /(\d+)/; # untaint port number
+
+    socket(Server, PF_INET, SOCK_STREAM, $proto)       || die "socket: $!";
+    setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, 
+                                       pack("l", 1))   || die "setsockopt: $!";
+    bind(Server, sockaddr_in($port, INADDR_ANY))       || die "bind: $!";
+    listen(Server,SOMAXCONN)                           || die "listen: $!";
+
+    logmsg "server started on port $port";
+
+    my $paddr;
+
+    $SIG{CHLD} = \&REAPER;
+
+    for ( ; $paddr = accept(Client,Server); close Client) {
+       my($port,$iaddr) = sockaddr_in($paddr);
+       my $name = gethostbyaddr($iaddr,AF_INET);
+
+       logmsg "connection from $name [", 
+               inet_ntoa($iaddr), "] 
+               at port $port";
+
+       print Client "Hello there, $name, it's now ", 
+                       scalar localtime, "\n";
+    } 
+
+And here's a multi-threaded version.  It's multi-threaded in that
+like most typical servers, it spawns (forks) a slave server to 
+handle the client request so that the master server can quickly
+go back to service a new client.
 
     #!/usr/bin/perl -Tw
     require 5.002;
@@ -473,10 +519,13 @@ the appropriate interface on multihomed hosts:
 
     my $port = shift || 2345;
     my $proto = getprotobyname('tcp');
-    socket(SERVER, PF_INET, SOCK_STREAM, $proto)       || die "socket: $!";
-    setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1)    || die "setsockopt: $!";
-    bind(SERVER, sockaddr_in($port, INADDR_ANY))       || die "bind: $!";
-    listen(SERVER,5)                                   || die "listen: $!";
+    $port = $1 if $port =~ /(\d+)/; # untaint port number
+    
+    socket(Server, PF_INET, SOCK_STREAM, $proto)       || die "socket: $!";
+    setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, 
+                                       pack("l", 1))   || die "setsockopt: $!";
+    bind(Server, sockaddr_in($port, INADDR_ANY))       || die "bind: $!";
+    listen(Server,SOMAXCONN)                           || die "listen: $!";
 
     logmsg "server started on port $port";
 
@@ -484,18 +533,18 @@ the appropriate interface on multihomed hosts:
     my $paddr;
 
     sub REAPER { 
-       $SIG{CHLD} = \&REAPER;  # loathe sysV
        $waitedpid = wait;
+       $SIG{CHLD} = \&REAPER;  # loathe sysV
        logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
     }
 
     $SIG{CHLD} = \&REAPER;
 
     for ( $waitedpid = 0; 
-         ($paddr = accept(CLIENT,SERVER)) || $waitedpid; 
-         $waitedpid = 0, close CLIENT) 
+         ($paddr = accept(Client,Server)) || $waitedpid; 
+         $waitedpid = 0, close Client) 
     {
-       next if $waitedpid;
+       next if $waitedpid and not $paddr;
        my($port,$iaddr) = sockaddr_in($paddr);
        my $name = gethostbyaddr($iaddr,AF_INET);
 
@@ -524,12 +573,12 @@ the appropriate interface on multihomed hosts:
            return;
        } elsif ($pid) {
            logmsg "begat $pid";
-           return; # i'm the parent
+           return; # I'm the parent
        }
-       # else i'm the child -- go spawn
+       # else I'm the child -- go spawn
 
-       open(STDIN,  "<&CLIENT")   || die "can't dup client to stdin";
-       open(STDOUT, ">&CLIENT")   || die "can't dup client to stdout";
+       open(STDIN,  "<&Client")   || die "can't dup client to stdin";
+       open(STDOUT, ">&Client")   || die "can't dup client to stdout";
        ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
        exit &$coderef();
     } 
@@ -584,7 +633,7 @@ differ from the system on which it's being run:
 
 =head2 Unix-Domain TCP Clients and Servers
 
-That's fine for Internet-domain clients and servers, but what local
+That's fine for Internet-domain clients and servers, but what about local
 communications?  While you can use the same setup, sometimes you don't
 want to.  Unix-domain sockets are local to the current host, and are often
 used internally to implement pipes.  Unlike Internet domain sockets, UNIX
@@ -629,18 +678,18 @@ And here's a corresponding server.
     my $uaddr = sockaddr_un($NAME);
     my $proto = getprotobyname('tcp');
 
-    socket(SERVER,PF_UNIX,SOCK_STREAM,0)       || die "socket: $!";
+    socket(Server,PF_UNIX,SOCK_STREAM,0)       || die "socket: $!";
     unlink($NAME);
-    bind  (SERVER, $uaddr)                     || die "bind: $!";
-    listen(SERVER,5)                   || die "listen: $!";
+    bind  (Server, $uaddr)                     || die "bind: $!";
+    listen(Server,SOMAXCONN)                   || die "listen: $!";
 
     logmsg "server started on $NAME";
 
     $SIG{CHLD} = \&REAPER;
 
     for ( $waitedpid = 0; 
-         accept(CLIENT,SERVER) || $waitedpid; 
-         $waitedpid = 0, close CLIENT) 
+         accept(Client,Server) || $waitedpid; 
+         $waitedpid = 0, close Client) 
     {
        next if $waitedpid;
        logmsg "connection on $NAME";
@@ -676,7 +725,7 @@ all, let alone in order and unmangled.  Still, UDP offers some advantages
 over TCP, including being able to "broadcast" or "multicast" to a whole
 bunch of destination hosts at once (usually on your local subnet).  If you
 find yourself overly concerned about reliability and start building checks
-into your message system, then you probably should just use TCP to start
+into your message system, then you probably should use just TCP to start
 with.
 
 Here's a UDP program similar to the sample Internet TCP client given
@@ -765,7 +814,7 @@ Here's an example of a semaphore:
     die if !defined($key);
     print "$key\n";
 
-Put this code in a separate file to be run in more that one process
+Put this code in a separate file to be run in more than one process.
 Call the file F<take>:
 
     # create a semaphore
@@ -789,7 +838,7 @@ Call the file F<take>:
 
     semop($key,$opstring) || die "$!";
 
-Put this code in a separate file to be run in more that one process
+Put this code in a separate file to be run in more than one process.
 Call this file F<give>:
 
     # 'give' the semaphore
@@ -827,14 +876,14 @@ find them at a CPAN store near you.
 If you are running under version 5.000 (dubious) or 5.001, you can still
 use most of the examples in this document.  You may have to remove the
 C<use strict> and some of the my() statements for 5.000, and for both
-you'll have to load in version 1.2 of the F<Socket.pm> module, which
-was/is/shall-be included in I<perl5.001o>.
+you'll have to load in version 1.2 or older of the F<Socket.pm> module, which
+is included in I<perl5.002>.
 
 Most of these routines quietly but politely return C<undef> when they fail
 instead of causing your program to die right then and there due to an
 uncaught exception.  (Actually, some of the new I<Socket> conversion
 functions  croak() on bad arguments.)  It is therefore essential
-that you should check the return values fo these functions.  Always begin
+that you should check the return values of these functions.  Always begin
 your socket programs this way for optimal success, and don't forget to add
 B<-T> taint checking flag to the pound-bang line for servers:
 
@@ -849,8 +898,8 @@ B<-T> taint checking flag to the pound-bang line for servers:
 All these routines create system-specific portability problems.  As noted
 elsewhere, Perl is at the mercy of your C libraries for much of its system
 behaviour.  It's probably safest to assume broken SysV semantics for
-signals and to stick with simple TCP and UDP socket operations; e.g. don't
-try to pass open filedescriptors over a local UDP datagram socket if you
+signals and to stick with simple TCP and UDP socket operations; e.g., don't
+try to pass open file descriptors over a local UDP datagram socket if you
 want your code to stand a chance of being portable.
 
 Because few vendors provide C libraries that are safely 
@@ -868,7 +917,7 @@ Besides the obvious functions in L<perlfunc>, you should also check out
 the F<modules> file at your nearest CPAN site.  (See L<perlmod> or best
 yet, the F<Perl FAQ> for a description of what CPAN is and where to get it.)
 Section 5 of the F<modules> file is devoted to "Networking, Device Control
-(modems) and Interprocess Communication", and contains numerous unbundled
+(modems), and Interprocess Communication", and contains numerous unbundled
 modules numerous networking modules, Chat and Expect operations, CGI
 programming, DCE, FTP, IPC, NNTP, Proxy, Ptty, RPC, SNMP, SMTP, Telnet,
 Threads, and ToolTalk--just to name a few.