Errata

Perl Cookbook

Errata for Perl Cookbook

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page xxx
2/3 down

s/printer pager/printer paper

... "greatly contributing to global deforestation"

Anonymous   
Printed Page Examples
The pcookexamples.tar.gz file on the ftp server

ftp://ftp.oreilly.com/pub/examples/perl/9781565922433/pcookexamples.tar.gz

When extracting the tar, the file

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

Anonymous   
Other Digital Version Parsing Dates and Times from Strings
1st Solution Box

On https://www.oreilly.com/library/view/perl-cookbook/1565922433/ch03s08.html

The example is not quite right, gives an answer a month out...

use Time::Local;
# $date is "1998-06-03" (YYYY-MM-DD form).
($yyyy, $mm, $dd) = ($date =~ /(\d+)-(\d+)-(\d+)/);
# calculate epoch seconds at midnight on that day in this timezone
$epoch_seconds = timelocal(0, 0, 0, $dd, $mm, $yyyy);


It should be:

use Time::Local;
# $date is "1998-06-03" (YYYY-MM-DD form).
($yyyy, $mm, $dd) = ($date =~ /(\d+)-(\d+)-(\d+)/);
# calculate epoch seconds at midnight on that day in this timezone
$epoch_seconds = timelocal(0, 0, 0, $dd, $mm-1, $yyyy);

because timelocal uses 0-11 for the months, like localtime does.

https://perldoc.perl.org/Time::Local says:
"It is worth drawing particular attention to the expected ranges for the
values provided. The value for the day of the month is the actual day
(i.e. 1..31), while the month is the number of months since January
(0..11). This is consistent with the values returned from localtime() and gmtime()."

Anonymous  Jul 04, 2022 
Printed Page 31
sub parse_csv

some local settings of MS Excel will generate CSV file with semicolon separator rather than comma. for general use of this subroutine I added variables and corrected this code so that it will return the fields "as is". Enclosing characters (double quotes) will also be returned:

my $separator = ';';
my $enclosure = '"';
my $escape = '"';

.....

push(@new, $+) while m{
($enclosure[^$enclosure$escape]*(?:$escape.[^$enclosure$escape]*)*$enclosure)$separator?
| ([^$separator]+)$separator?
| $separator
}gx;

push(@new, undef) if substr($_, -1,1) eq $separator;

......

Yannis L.  Jun 26, 2009 
Printed Page 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/(ddd)(?=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/(.dd).*$/$1/;

Then the text can be printed with the '%21s' formatting string.

Anonymous   
Printed Page 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 ?

Anonymous   
Printed, PDF Page 187
Second to last line on the page.

Missing right squiggly bracket after "Punctuation". The

[\p{Space}\p{Punctuation]

should be:

[\p{Space}\p{Punctuation}]

Marnix A. van Ammers  Sep 22, 2022 
Printed Page 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.

Anonymous   
Printed Page 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"
}, $addr, $addr, $addr, scalar <>;
Should read:
printf qq{%#x %#o %d "%s"
}, $addr, $addr, $addr, scalar <FH>;

Anonymous   
Printed Page 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 ...

Anonymous   
Printed Page 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('<Configure>' 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.

Anonymous   
Printed Page 591
2nd paragraph

waitpid() should be called with WNOHANG rather than &WNOHANG

Anonymous   
Printed Page 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.

Anonymous   
Printed, Page 624
Solution, 17.11 Forking Server

The REAPER function uses the following loop to prevent zombies:

1 until (-1 == waitpid(-1, WNOHANG));

While this will clean up your dead children, it has the unfortunate property of looping until all current children are complete, since waitpid(-1, WNOHANG) returns 0 if there are any current children.

A better solution would be either

1 until( 0 >= waitpid(-1, WNOHANG));

or

1 while (waitpid(-1, WNOHANG) > 0));


Anonymous  Jul 25, 2011 
Printed Page 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';

Anonymous   
Printed Page 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.

Anonymous   
Printed Page 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.

Anonymous   
638
Section 16.8, "Solution"

The example given for open2() is:

$pid = open2(*README, *WRITEME, $program) ;

However, open2() uses this argument order (from the pod documentation):

$pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some cmd and args');

In other words, the output file handle comes first, then the input one. The example as given in the book will not work.

IMPORTANT NOTE: open3() in IPC::Open3 uses the input, output and error file handles as the first three arguments. In other words, its argument order is different from open2() in IPC::Open2.

Jim Goltz  Mar 10, 2010 
Printed Page 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");

Anonymous   
Printed Page 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.

Anonymous   
Printed Page 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+) ([^]]+)]

Anonymous