| Goals for this chapter: | rpm packages covered in this chapter:
|
|
|
|
Larry Wallman develop the PERL language like an alternative to awk and sed scripts, in 1988, Jan 31.
Today PERL is one of the most used Programming Languages in Linux, from CGI and Web site script development as well as the language used for example by Mandrake Soft in its installer as well as its sysadm scripts.
PERL is not really complex but is different than C or awk/sed scripting languages.
For example we can see code like:
my $input = <STDIN>;
my $username = chop( $input );
print "$username";
Actually the PERL and Python teams are working to create a new programming language called Parrot, that will continues the development of these
PERL is binary generally located in "/usr/bin"
[root@ftosx1 PERL]# which perl
/usr/bin/perl
[root@ftosx1 PERL]# file `which perl`
/usr/bin/perl: ELF 32-bit LSB executable, Intel 80386, version
1, dynamically linked (uses shared libs), stripped
[root@ftosx1 PERL]#
PERL may be used in different modes.
The most classical mode is to create an ASCII executable file, which the first line is
#!/usr/bin/perl -w
...
PERL code
...
EOF
There are also other mode to run PERL, like a single command line command
[root@ftosx1 PERL]# perl -wle '$radius = 34; print $radius;'
34
[root@ftosx1 PERL]#
In the next sections we will cover and explain how to create programs in PERL
In Appendix L: Learning a Programming Language syntax in one day, we introduce a fast mode to learn a syntax for a specific language:
Declarations
PERL is similar to C and BASH.
Data Declaration is as follows:
$a = 90.27
A simple program to print a value in PERL may be:
#!/usr/bin/perl -w
$a = 90.3;
print "$a\n";
Note that the print statement includes a variable: $a, between quotes, including a non variable \n.
Also note that all the statement needs a semicolon: ";".
We can for example write a program to transform italian liras to euros, that haves a fixed rate.
[root@ftosx1 PERL]# more ./it2euro.pl
#!/usr/bin/perl -w
$it2euro = 1926.29;
$one_milion_liras=1000000;
$result=$one_milion_liras*$it2euro;
print "One million liras are $result \n";
[root@ftosx1 PERL]#
[root@ftosx1 PERL]# ./it2euro.pl
One million liras are 1926290000
[root@ftosx1 PERL]#
Now, will modify this source to convert US$ Dollars to Euros. This rate changes everyday, therefore we will apply the change for today.
1 US Dollar = 1.18147 Euro
We will also add a "input" mode to the previous program.
At first we make some input/output tests
[root@ftosx1 PERL]# more dollar2euro.pl
#!/usr/bin/perl -w
print "Enter US\$ dollar to transfrom in euro \n";
$input = <STDIN>;
print "You enter $input \n";
[root@ftosx1 PERL]#
[root@ftosx1 PERL]# ./dollar2euro.pl
Enter US$ dollar to transfrom in euro
90
You enter 90
[root@ftosx1 PERL]#
Now, we add the math!
#!/usr/bin/perl -w
print "Enter US\$ dollar to transfrom in euro: ";
$input = <STDIN>;
$result = $input*1.18147;
print "$input dollars are $result euros\n";
Enter US$ dollar to transfrom in euro: 90
90
dollars are 106.3323 euros
[root@ftosx1 PERL]#
As we note that there are some special character in the input data. PERL offer the chop, to clean all not necessary data.
#!/usr/bin/perl -w
print "Enter US\$ dollar to transfrom in euro: ";
chop($input = <STDIN>);
$result = $input*1.18147;
#$result = chop ($result);
print "$input dollars are $result euros\n";
And we will have the right result!
[root@ftosx1 PERL]# ./dollar2euro.pl
Enter US$ dollar to transfrom in euro: 249.95
249.95 dollars are 295.3084265 euros
[root@ftosx1 PERL]#
PERL includes different components in its distribution, and the mode to use it is different than normal Linux or X Window functions.
To know the components included in the PERL Distribution we have
PERL(1) Perl Programmers Reference Guide PERL(1)
NAME
perl - Practical Extraction
and Report Language
SYNOPSIS
perl [ -sTuU ]
[ -hv ] [ -V[:configvar] ] [ -cw ] [ -d[:debugger]
] [ -D[number/list] ]
[ -pna ] [ -Fpattern ] [ -l[octal] ] [ -0[octal] ]
[ -Idir ] [ -m[-]module ] [ -M[-]'module...' ]
[ -P ] [ -S ]
[ -x[dir] ] [ -i[extension] ]
[ -e 'command' ] [ -- ] [ programfile ] [ argument ]...
For ease of access, the Perl manual has been split up into a number of sections:
perl
Perl overview (this section)
perldelta Perl
changes since previous version
perl5004delta Perl changes in version
5.004
perlfaq
Perl frequently asked questions
perltoc
Perl documentation table of contents
perldata
Perl data structures
perlsyn
Perl syntax
perlop
Perl operators and precedence
perlre
Perl regular expressions
perlrun
Perl execution and options
perlfunc
Perl builtin functions
perlopentut Perl open()
tutorial
perlvar
Perl predefined variables
perlsub
Perl subroutines
perlmod
Perl modules: how they work
perlmodlib Perl modules:
how to write and use
perlmodinstall Perl modules: how to install
from CPAN
perlform
Perl formats
perllocale Perl locale
support
perlref
Perl references
perlreftut Perl references
short introduction
perldsc
Perl data structures intro
perllol
Perl data structures: lists of lists
perltoot
Perl OO tutorial
perlobj
Perl objects
perltie
Perl objects hidden behind simple variables
perlbot
Perl OO tricks and examples
... (There are more ...)
For example, to get the manual entry for the "chop" function we need to run:
[root@ftosx1 /root]# perldoc -f chop
... and we will get.
=item chop VARIABLE
=item chop LIST
=item chop
Chops off the last character of a string and returns the character
chopped. It's used primarily to remove the newline from
the end of an
input record, but is much more efficient than C<s/\n//> because
it neither
scans nor copies the string. If VARIABLE is omitted, chops
C<$_>.
Example:
while (<>) {
chop;
# avoid \n on last field
@array = split(/:/);
#...
}
You can actually chop anything that's an lvalue, including an assignment:
chop($cwd = `pwd`);
chop($answer = <STDIN>);
If you chop a list, each element is chopped. Only the value
of the
last C<chop()> is returned.
Note that C<chop()> returns the last character. To return
all but the last
character, use C<substr($string, 0, -1)>.
(END)
Perl includes a special variable: $_
[root@ftosx1 PERL]# more Using_dollar_
#!/usr/bin/perl
$_= "We will print the content of this variable without to use it!\n";
print; # Look. There are no variable ...
[root@ftosx1 PERL]#
[root@ftosx1 PERL]# ./Using_dollar_
We will print the content of this variable without to use it!
[root@ftosx1 PERL]#
Look that there are no variable near to the print command.
PERL like Tcl and other languages offers the possibility to works with Arrays, also called list.
[root@ftosx1 PERL]# more array.pl
#!/usr/bin/perl -w
@my_net = qw(world ftosx1 ftosx2 heaven www thunder wind earth);
print "@my_net\n";
[root@ftosx1 PERL]# ./array.pl
world ftosx1 ftosx2 heaven www thunder wind earth
PERL can understand the list also like
[root@ftosx1 PERL]# more array2.pl
#!/usr/bin/perl -w
@my_net = qw(world ftosx1 ftosx2 heaven www thunder wind earth);
foreach $record (@my_net) {
print "$record\n";
}
[root@ftosx1 PERL]#
[root@ftosx1 PERL]# ./array2.pl
world
ftosx1
ftosx2
heaven
www
thunder
wind
earth
[root@ftosx1 PERL]#
PERL support normal operations on arrays: join, split, sort and others.
In the previous sections we introduce PERL scalars ...
$my_var=34.756;
arrays also called lists ...
@star_trek_movies = qw('The Motion Picture' 'The Wrath Of Khan' 'The Search For Spock ' 'The Voyage Home' 'The Final Frontier ' 'The Undiscovered Country' ' First Contact' 'Generations' 'Insurrection');
and now the Hash.
The Hash is a simple and intelligent mode to handle data using keys. Is possible to transform data from hash to lists whwn necessary. Hash is a mode to work with small database, or to create ASCII database with normal Linux/UNIX data.
[root@ftosx1 PERL]# more hash1.pl
#!/usr/bin/perl -w
%LinuxCompanies=( 'Caldera' => 'Utah',
'Red Hat' => 'North Carolina',
'SuSE' => 'Nurnberg',
'Mandrake' => 'Paris',
'Future Technologies' => 'California');
print $LinuxCompanies{'Red Hat'};
print "\n";
[root@ftosx1 PERL]# ./hash1.pl
North Carolina
[root@ftosx1 PERL]#
The hash is LinuxCompanies. Where each Linux compnay haves a key, that is the city.
These examples may be used in different situations from SysAdm or to simple File Handling.
We present here a simple version using the special "$_"
[root@ftosx1 PERL]# more hash3.pl
#!/usr/bin/perl -w
%LinuxCompanies=( 'Caldera' => 'Utah', 'RedHat' => 'North Carolina',
'SuSE' => 'Nurmebrg', 'Mandrake' => 'Paris', 'Future Technologies' => 'California');
@Data=%LinuxCompanies;
foreach(@Data) {
print "$_\n";
}
[root@ftosx1 PERL]# ./hash3.pl
Caldera
Utah
SuSE
Nurmebrg
Future Technologies
California
RedHat
North Carolina
Mandrake
Paris
[root@ftosx1 PERL]#
PERL offers the special variable @_, to pass arguments. We introduce here in a simple example.
[root@ftosx1 PERL]# more hash5.pl
#!/usr/bin/perl -w
$time = 0;
sub printargs {
print join (',', @_);
$time += 1;
print $time;
}
printargs ('Caldera', 'RedHat', 'North Carolina', 'SuSE', 'Mandrake', 'Future Technologies');
[root@ftosx1 PERL]# ./hash5.pl
Caldera,RedHat,North Carolina,SuSE,Mandrake,Future Technologies1[root@ftosx1
PERL]#
The argument @_ create the chain in a single call, resuming all the parameters.
We will complete this section with some usefull tables:
|
|
|
Control-Flow
The Control-Flow in PERL is very simple and similar to C or other languages.
Following the Appendix L model, we have:
|
|
|
|
| if ($x > $ y) {
print "$x is high than $y"; } elseif ($x < $y) { print "$x is high than $y"; } else { print "$x is equal than $y"; } or if($ENV{'HTTP_REFERER'} =~ /$valid_domains/gi && !$ENV{'QUERY_STRING'}) { $username =~ s/ /_/g;
or if ($hour%2 == 0) {
|
print "$i\n"; }
foreach $record (@my_net) { print "$record\n"; } Use: for with "{" "}" |
{ ($char) = split (//, $_); print "The first char you inout was $char\n"; } |
File I/O
PERL support standard functions to handle files: "open", "close".
For example a program in PERL that open a file a list it, may be:
#!/usr/bin/perl -w
open (MYFILE, "printcap") || die "opening testfile";
@stuff=<MYFILE>;
close(MYFILE);
print @stuff;
[root@ftosx1 PERL]#
To write files in PERL is used
#!/usr/bin/perl -w
open (SOURCE, "printcap") || die "$!";
open (DEST, ">destination") || die "$!";
@contents=<SOURCE>;
print DEST @contents;
close(DEST);
close(SOURCE);
[root@ftosx1 PERL]# ./writefile.pl
[root@ftosx1 PERL]# diff printcap destination
[root@ftosx1 PERL]#
PERL support also BINARY files like GIF, and others using the binmode attrib.
open (FH, "mywordfile.doc") || die "$!";
binmod (FH);
close (FH);
Now, that we knows some basic know-how about PERL, its Control-Flow and File I/O, we can create some interesting examples.
However, before to introduce some examples we want to cover how functions are used in PERL Programming.
We start with an elementary mode, calling a function: BEGIN
[root@ftosx1 PERL]# more !$
more ./functions.pl
#!/usr/bin/perl -w
sub BEGIN {
for ($i=1; $i<=10;
$i++) {
print "$i\n";
}
}
BEGIN;
[root@ftosx1 PERL]#
This means that the function BEGIN is called when the program touchs the position BEGIN.
[root@ftosx1 PERL]# ./functions.pl
1
2
3
4
5
6
7
8
9
10
[root@ftosx1 PERL]#
Now, we will transform this program to a program using functions, reading the Standard Input.
[root@ftosx1 PERL]# more !$
more functions2.pl
#!/usr/bin/perl -w
sub do_the_sum {
$sum = 0;
for ($i=1; $i<=$mylast;
$i++) {
$sum += $i;
}
return ($sum);
}
$mylast = <STDIN>; chop $mylast;
print do_the_sum(@mylast) ,"\n";
[root@ftosx1 PERL]#
Look what is the parameter, @mylast and the variable inside the function $mylast. Here we write a similar function and call it with a parameter.
[root@ftosx1 PERL]# ./functions2.pl
34
595
[root@ftosx1 PERL]#
Now, we will introduce the strict module. Using this module each variable will need to be assigned to a $my variable.
This program simply print the sum of all arguments.
[root@ftosx1 PERL]# more functions3.pl
#!/usr/bin/perl -w
use strict;
sub thesum {
my(@data)=@_;
my $i;
my $sum = 0;
foreach (@data) {
$sum+=$_;
}
return($sum);
}
my($data, @dataset);
print "Please enter data, separated by commas: ";
$data=<STDIN>; chomp $data;
@dataset=split(/[\s,]+/, $data);
print "Sum: ", thesum(@dataset), "\n";
[root@ftosx1 PERL]#
From PERL 5.0, PERL start to works with modules.
The repositore for PERL modules is the CPAN: Comprehensive Perl Archive Network
There are modules for everything:
The complete PERL 5 Module list is available at: PERL
5 Module List
We here we will list a couple of examples
[root@ftosx1 PERL]# ls modules*
modules2.pl modules.pl
[root@ftosx1 PERL]# more modules2.pl
#!/usr/bin/perl -w
use File::Copy;
copy ("modules2.pl", "modules3.pl") || warn "Could not copy files: $!";
[root@ftosx1 PERL]# ./modules2.pl
[root@ftosx1 PERL]# ls modules*
modules2.pl modules3.pl modules.pl
[root@ftosx1 PERL]#
In the previous example we use the module File::Copy.
Now, we will introduce an example but the Ping module haves a bug. The PERL module haves a bug. We prefer to cover it anyway because, to teach that tests need to be made all the time.
This is the script.
[root@ftosx1 PERL]# more modules.pl
#!/usr/bin/perl -w
use Net::Ping;
print "Enter remote server to ping: ";
chop($server = <STDIN>);
if (pingecho ($server,
15) ) {
print "The remote system is up!\n";
} else {
print "The remote system is down!\n";
}
[root@ftosx1 PERL]#
Now, we test it with different servers
[root@ftosx1 PERL]# ping 192.168.1.64
PING 192.168.1.64 (192.168.1.64) from 192.168.1.93 : 56(84)
bytes of data.
Warning: time of day goes back, taking countermeasures.
64 bytes from 192.168.1.64: icmp_seq=0 ttl=64 time=1.161 msec
64 bytes from 192.168.1.64: icmp_seq=1 ttl=64 time=1.126 msec
--- 192.168.1.64 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/mdev = 1.126/1.143/1.161/0.038 ms
[root@ftosx1 PERL]# ./modules.pl
Enter remote server to ping: 192.168.1.64
The remote system is up!
[root@ftosx1 PERL]#
But, now testing another server.
[root@ftosx1 PERL]# ping 192.168.1.60
PING 192.168.1.60 (192.168.1.60) from 192.168.1.93 : 56(84)
bytes of data.
Warning: time of day goes back, taking countermeasures.
64 bytes from 192.168.1.60: icmp_seq=0 ttl=255 time=774 usec
--- 192.168.1.60 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/mdev = 0.774/0.774/0.774/0.000 ms
The server is up ... but the program does not get the right answer!
[root@ftosx1 PERL]# ./modules.pl
Enter remote server to ping: 192.168.1.60
The remote system is down!
[root@ftosx1 PERL]#
The answer to this incomplete job, is because probably there are no a complete compatibility with the ping perl function and the network functions.
The system will works is a very old kernel.
[root@earth /root]# uname -r
2.0.33
[root@earth /root]#
While this function does not work neither locally!
[root@ftosx1 PERL]# hostname -i
192.168.1.93
[root@ftosx1 PERL]# ./modules.pl
Enter remote server to ping: 192.168.1.93
[root@ftosx1 PERL]# uname -r
2.4.7-2
[root@ftosx1 PERL]#
In the previous sections we introduce strict and also other modules.
The WebMaster generally uses this modules to and others specially created like the CGI module.
This module is excellent to create HTML pages including forms, in seconds.
For example you can use:
0::CGI(3) User Contributed Perl Documentation
.0::CGI(3)
NAME
CGI - Simple Common Gateway
Interface Class
SYNOPSIS
# CGI script
that creates a fill-out form
# and echoes
back its values.
use CGI qw/:standard/;
print header,
start_html('A Simple Example'),
h1('A Simple Example'),
start_form,
"What's your name? ",textfield('name'),p,
"What's the combination?", p,
checkbox_group(-name=>'words',
-values=>['eenie','meenie','minie','moe'],
-defaults=>['eenie','minie']), p,
"What's your favorite color? ",
popup_menu(-name=>'color',
-values=>['red','green','blue','chartreuse']),p,
submit,
end_form,
hr;
if (param())
{
print "Your name is",em(param('name')),p,
"The keywords are: ",em(join(", ",param('words'))),p,
"Your favorite color is ",em(param('color')),
hr;
}
ABSTRACT
This perl library uses
perl5 objects to make it easy to
create Web fill-out forms
and parse their contents. This
package defines CGI objects,
entities that contain the
values of the current query
string and other state vari
ables. Using a CGI
object's methods, you can examine key
words and parameters passed
to your script, and create
forms whose initial values
are taken from the current
query (thereby preserving
state information). The module
provides shortcut functions
that produce boilerplate HTML,
reducing typing and coding
errors. It also provides func
tionality for some of the
more advanced features of CGI
scripting, including support
for file uploads, cookies,
cascading style sheets,
server push, and frames.
The remote system is down!
[root@ftosx1 PERL]#
Server-Side Includes
The WebMaster figure is everyday a mix between a programmer and a System Administrator.
The SSI, or Server-Side Includes or server-parsed HTML, is a simple technique that allow to create HTML pages on the fly using PERL scripts, that build pages; dynamic pages, automatically.
This technique is probably the original expected technique, before to start to study CGI.
The SSI works as follows.
The server load a SHTML or STM page, that includes a command like:
<!--exec cgi="/cgi-bin/cgi.pl"-->
This command expect an executable file called cgi.pl, in the CGI dir present in the Apache httpd.conf file.
Is fundamental that that file extension is SHTML or STM.
We will start presenting a simple example that write an HTML page using CGI and SSI technique.
Following the previous introduction we need to write two files:
The SHTML file and the CGI PERL script
[root@www /root]# cd /var/www
[root@www www]# ls
cgi-bin html html.old html-previous.tgz
html.tgz icons nut-cgi-bin
[root@www www]#
Now, we list the simple SHTML file.
[root@www www]# more html/boilerplate.shtml
<HTML>
<HEAD>
<TITLE>Welcome Page</TITLE>
</HEAD>
<BODY>
Welcome
<!--#exec cgi="/cgi-bin/cgi.pl"-->
</BODY>
</HTML>
[root@www www]#
and now we list the PERL Script.
#!/usr/bin/perl -w
use CGI qw(:all);
use strict;
print header, start_html('Title'),
h1('hello world'),
end_html;
[root@www www]#
As we can see, generate a page like using the PERL CGI module is quite easy.
After we choose the SHTML page we will get:

In true SSI are used to create dynamic pages, that is different pages in different moments.
Now, we update the boilerplate.shtml file to load a new file.
<!--#exec cgi="/cgi-bin/cgi2.pl"-->
The new script present two different images in different moments.
| Each even minute ... you will get ... | Each odd minute ... you will get ... |
![]() |
![]() |
This may be used for banners that each minute changes its anymated gif
that we introduce in Chapter
The PERL CGI module may be used also to create forms, like we list here:
use CGI qw(:standard);
print header;
print start_html('Form Example'),
h1('My Example Form'),
start_form,
"Name: ", textfield('name'), p,
"Age: ", textfield('age'), p,
submit,
end_form;
if(param()) {
print "Hi ",em(param('name')),
"You are ",em(param('age')),
" years old";
}
print end_html;
PERL and the CGI module allow also to test the browser used.
This simple script complete this task.
[root@www cgi-bin]# more browser.pl
#!/usr/bin/perl -w
use CGI qw(:all);
use strict;
my($browser, $mynetscape, $myother);
$mynetscape = "http://www.futuretg.com/index.html"
$myother = "http://www.futuretg.com/index.html"
$browser = user_agent;
if ($browser =~ /Mozilla/ ) {
print redirect (
-uri => $mynetscape);
} else {
print redirect (
-uri => $myother);
}
[root@www cgi-bin]#
Check CGI documentation for additional info.
One of the most innovative and intelligent new techologies to follows Web visitor is the cookie.
The cookie is similar to a parking ticket. When you park your car you receive a ticket. When you back you will pay the time your car was parking there and they will authorize you get back your card.
The ticket will be the "document" that people will recognize to authorize you to pay and get back the car.
Is not important the time, may be also years, the important is the ticket.
In the same sense the cookies are your "tickets" when you back to vist your favorite Web sites.
Amazon.com, dvdexpress and also our simple Future TechClub and Store handle cookies.
cookies have the following format:
$mycookie = cookie (-name => cookie_name,
-value => cookie_value,
-expires => expiration,
-path => path_info,
-domain => domain_info,
-secure => true or false );
Cookies are set on the browser for a period of time.
Here we will list some simple examples about cookies.
#!/usr/bin/perl -w
use strict;
use CGI qw(:all);
my $cookie = cookie (-name => 'My Sample', -value => 'Cookie without a value');
print header(-cookie => $cookie);
We can assign also a time to the cookie:
#!/usr/bin/perl -w
use strict;
use CGI qw(:all);
my $cookie = cookie (-name => 'My Cookie', -value => 'The NeXT book', -expires => '+8d');
print header(-cookie => $cookie);
Now, we list a little more complex example:
[root@www cgi-bin]# more cookie2.pl
#!/usr/bin/perl -w
use strict;
use CGI qw(:all);
use CGI::Carp qw(fatalsToBrowser);
my($requested_color, $old_color, $color_cookie)=("","");
$old_color="blue"; # Default value
# Is there a new color requested?
if (defined param('color')) {
$requested_color=param('color');
}
# What was the old color, if any?
if (defined cookie('bgcolor')) {
$old_color=cookie('bgcolor');
}
if ($requested_color and ($old_color ne $requested_color)) {
# Set the cookie
in the browser
$color_cookie=cookie(-name
=> 'bgcolor',
-value => $requested_color);
print header(-cookie
=> $color_cookie);
} else {
# Nothing's changed,
no need to set the cookie
$requested_color=$old_color;
print header;
}
print<<END_OF_HTML;
<HTML>
<HEAD>
<TITLE>Set your background color</TITLE>
</HEAD>
<BODY BGCOLOR="$requested_color">
<FORM>
<SELECT NAME="color">
<OPTION value='red'>Red
<OPTION value='blue'>Blue
<OPTION value='yellow'>Yellow
<OPTION value='white'>White
</SELECT>
<INPUT TYPE=SUBMIT VALUE="Set the color">
</FORM>
</BODY>
</HTML>
END_OF_HTML
This example allow to change the background checking the cookie name
and the scroolbar.

In the previous example cookies are equivalent to actual local variables on the Browser.
Generally cookies are not recognized after the Browser cache become clean.
PERL or Practical Extraction and Report Language is of course a fundamental programming language for a Linux programmers as well as the WebMaster.
While the System Administrator may or may not learn PERL, because he can use Tcl, Expect, BASH, C or C++ programming languages to solve a specific task, the WebMaster necessary need to lear PERL.
As covered here, PERL is different to Tcl, or C, or Java, or sed or awk, but really powerfull.
The original image for PERL (see below) represent the language, similar
to the bash more powerfull, but you need a little bit be a PERL expert
![]() |
![]() |
| Original PERL image |
|
The 2001, is the year of PERL 6.0. Larry Wallman and Guido van Rossum
and its team are working to create a new language that resume both PERL
and Python. To lear about Python please read the Chapter
11. An overview on Python in the Programming Course.
![]() |
|
|
We list here three links:
We suppose that about April 2002, Parrot will start to be used officially offering (like now) tools to move from PERL 5 to Parrot (or Perl 6).Check the Interactive Exam Cram WebMaster:
Internet Resources for this Chapter.