Perl Cookbook by Tom Christiansen & Nathan Torkington Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. This page was updated December 11, 2003. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and comments from readers: (Examples) The pcookexamples.tar.gz file on the ftp server; ftp://ftp.oreilly.com/pub/examples/perl/cookbook/pcookexamples.tar.gz When extracting the tar, the file cookbook.examples/ch17/nonforker Contains a type on line 89 it reads: {$! == POSIX::EWOULDBLOCK) { it should read: $! == POSIX::EWOULDBLOCK) { (ie there is an extra open-curly-brace at the start of the line) (xxx) 2/3 down; s/printer pager/printer paper ... "greatly contributing to global deforestation" (64) last paragraph; The commify subroutine attempts to return a scalar value of the commified text, but perl versions 5.005_03 and v5.6.0 appear to truncate everything from the first comma on, turning 123,456,789 into 123. Also, the attempt to return the reverse of the formatted text seems to fail. My corrected version is as follows: sub commify { my $text = reverse $_[0]; $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; $text = reverse $text; return $text; } This appears to work without loss in both perl versions mentioned, though the text returned must be formatted and printed as text, not a scalar value. In order to simulate the %9.2f formatting for a scalar value, the commified text was filtered with the following expression: $comm_text =~ s/(\.\d\d).*$/$1/; Then the text can be printed with the '%21s' formatting string. [177] 6.8 Solution description Koanstyle; 1st paragraph: "The operator ... doesn't return true if both its tests are true on the same line" last paragraph: "The ... operator doesn't test both conditions at once if the first one is true." The resolution happens on p179 2nd paragraph: ".. will not print any further lines." (if both tests are true) "OTOH, ... will continue until the *next* line matches /end/ because it never tries to test both" i.e. There is a condition zero "most_recent_condtion_that_was_true" which is initialized to "theSecond" and the first paragraph is wrong ? [245] 1st paragraph of the "Discussion"; "The numbers are normally represented by names like LOCK_EX, which you can get from the Fcntl or IO::File modules." IO::File does not export LOCK_EX, LOCK_SH, LOCK_NB, LOCK_UN by default or when you ask it to. A quick look at IO::File (v1.09) eval { # Make all Fcntl O_XXX constants available for importing require Fcntl; my @O = grep /^O_/, @Fcntl::EXPORT; Fcntl->import(@O); # first we import what we want to export push(@EXPORT, @O); }; shows that that only constants beginning with O_ are exported. {297} 1st paragraph; In example 8-5 bgets, the line printing the string doesn't read from the opened filehandle, thus ignoring the seek completely and always reading from offset 0. The line: printf qq{%#x %#o %d "%s"\n}, $addr, $addr, $addr, scalar <>; Should read: printf qq{%#x %#o %d "%s"\n}, $addr, $addr, $addr, scalar ; [330] in sub wanted; 1 if (-d _) { # then make a real directory 2 mkdir("$dstdir/$name", $mode) 3 or die "can't mkdir $dstdir/$name: $!"; should be if (-d $_) { # then make a real directory unless (-d "$dstdir/$name") { mkdir("$dstdir/$name", $mode) or die "can't mkdir $dstdir/$name: $!"; } the $_ is mangled in line1, and the mkdir will return error, because $dstdir has just been created in the previous for loop ... [542] bottom; You promise a recipe to suppress the USER to resize a Perl/Tk window. However, with the given recipe also the PROG won't adapt the window size anymore. Instead of $main->bind('' etc etc ), simply use $main->resizable(0,0). The recipe would look trivial then, but would hold the promise: No resizing by user, but no restraint to prog. {591} 2nd paragraph; waitpid() should be called with WNOHANG rather than &WNOHANG [617] Code under Discussion; The code for using IO::Socket for a Unix socket does not work. Even after modifying the the most recent Errata: $sock = IO::Socket::UNIX->new( Local => "/tmp/mysock", Type => SOCK_DGRAM, Listen => 5 ) or die $@; Generates a simple died error. Changing the last line to or die $!; gives more detail: Operation not supported on transport endpoint at ./server-u.pl line 9. Removing the Listen => 5 makes it work. HOWEVER: Using this code snippet, and the client/server UDP code from page 615-616, I can not get a working Unix domain client/serv er to pass a message. The client passes to the server, but the server dies with No such file or directory at ./server-u.pl line 19. When it tries to send the message back. A full example of working client/servers for the Unix domain would probably be helpfull. {629} line 10; in example 17-6 nonforker, the use of tie seems to be required for all 3 hashes (%inbuffer, %outbuffer, and %ready), but the example only tied the %ready hash. I think the following 2 statements are missing in the example: tie %inbuffer, 'Tie::RefHash'; tie %outbuffer, 'Tie::RefHash'; ?635? "Solution" example starting at end of page: The example describes how a signal handler can be used to restart a process using a HUP signal. In the HUP handler routine, phoenix(), the PERL exec() routine is used to start a new executable. Referencing "Programming Perl", 2nd edition (the camel book), page 163, the PERL exec() routine uses the execvp(3) system call to implement its functionality. The execvp() call causes the new process to inherit many of the process attributes from the calling process, including the process signal mask (see sigprocmask(2)). When the phenix() handler is executed, the process has the HUP signal blocked. Therefore, this example works only for the first time that the HUP signal is sent to the process. All subsequent signals have no effect. I have tested the example code, and I found this to be true (using the Solaris psig command to display the signal status). One solution to this problem would be to use the POSIX module to unblock the signal after it is restarted. Unfortunately for me, this example is only similar to my personal coding problem. I encountered this same bug in some PERL code that can be loosely described to work like inetd. In my case, I expected and need exec() to call execl() not execvp(). Any suggestions as to how I can get my PERL code to use execl() would be appreciated. [635] 7th paragraph; The solution descriped to 17.16 only seems to catch the first HUP signal, not the following ones. I've tried re-install the HUP handler after it's been called, but still no luck. I've tried the sample code on both FreeBSD and Linux. I checked teh Errata for my edition (August 1998) and found a typo, but nothing relating to the solution. Additionally, I searched on google's usenet search and it seems others have had similar problems. (652) 3rd program block; $mailer = Mail::Mailer->new("smtp", "mail.myisp.com"); is an obsolete syntax that does not work with newer Mailer versions. It should now read: $mailer = Mail::Mailer->new("smtp", Server=>"mail.myisp.com"); (716) 90 mm down from top of page; Book recommends using module HTML::Parse . This module has been depricated. http://www.perldoc.com/perl5.6.1/lib/HTML/Parse.html HTML::Parser is now typically advocated as a having superceded HTML:Parse. [727] 20.12 solution; The solution won't work. The regular expression used to split the line has a flaw. of the date-time-timezone part, the closing square bracket ']' is missing: \[([^:]+):(\d+:\d+:\d+) ([^\]]+) should become \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\]