Cover | Table of Contents | Colophon
http://www.opensource.org/) is a
relatively new name for a relatively old phenomenon. It refers to
software whose original instructions, or source
code, are made freely available to anyone who uses that
software. The opposite of open source is
proprietary (or closed
source) software,http://www.opensource.org/) is a
relatively new name for a relatively old phenomenon. It refers to
software whose original instructions, or source
code, are made freely available to anyone who uses that
software. The opposite of open source is
proprietary (or closed
source) software, in which users have
access only to the compiled binary form of the program—that is,
the executable that actually runs on the
computer.
ping and
traceroute commands. These utilities let you probe
a TCP/IP network (like the Internet) to see where your data packets
are going, how long it's taking them to get there, and whether
any of them are getting lost along the way. (See Packet-Switching 101 if these concepts are
new to you.)
http://winscp.vse.cz/eng/) offers a nice
Windows implementation of the secure scp protocol (which uses ssh
for security) to do file transfers. For Mac users, the aforementioned
NiftyTelnet (http://andrew2.andrew.cmu.edu/dist/niftytelnet.html)
also does scp file transfers. (Mac users running
OS X can also use the scp command-line
program directly.)
emacs
and
vi
(the latter pronounced
"vee-eye"). Both are extremely powerful and
full-featured. Both can also be a bit intimidating for beginners.
Because of that, I'm actually going to focus on a simpler
(albeit less powerful) editor called
pico
for this book's
text-editing-under-Unix examples. If pico is not
available on your system, you may need to buckle down and learn
emacs or vi whether you want to
or not. In that case, see The Traditional Unix Editors: emacs and vi
later in this chapter.
which
perl
. The which command
prints out the full path to the program that will run when you enter
the program's name by itself:
[jbc@andros jbc]$ which perl
/usr/bin/perl
perl
interpreter is located at /usr/bin/perl. Your copy
of perl may be located somewhere else. Wherever it
is, write down the location. You'll need to know it later.
which
command, you can try finding the location of Perl using the similar
command whereis
, giving it the -b
option to limit its output to binary files, as in:
[jbc@andros jbc]$ whereis -b perl
perl: /usr/bin/perl /usr/local/bin/perl
which command doesn't give you
any output, and just dumps you back to the shell prompt?
[jbc@andros jbc]$ which perl
[jbc@andros jbc]$
[jbc@andros jbc]$ which perl
which: no perl in (/usr/bin:/bin:/usr/local/bin)
which
perl
. The which command
prints out the full path to the program that will run when you enter
the program's name by itself:
[jbc@andros jbc]$ which perl
/usr/bin/perl
perl
interpreter is located at /usr/bin/perl. Your copy
of perl may be located somewhere else. Wherever it
is, write down the location. You'll need to know it later.
which
command, you can try finding the location of Perl using the similar
command whereis
, giving it the -b
option to limit its output to binary files, as in:
[jbc@andros jbc]$ whereis -b perl
perl: /usr/bin/perl /usr/local/bin/perl
which command doesn't give you
any output, and just dumps you back to the shell prompt?
[jbc@andros jbc]$ which perl
[jbc@andros jbc]$
[jbc@andros jbc]$ which perl
which: no perl in (/usr/bin:/bin:/usr/local/bin)
perl when you used the which
command. The next thing to do is to figure out what version it is. To
do that, you run the perl
program itself with a
-v command-line switch:
[jbc@andros jbc]$ perl -v
This is perl, v5.6.1 built for i586-linux
Copyright 1987-2001, Larry Wall
Perl may be copied only under the terms of either the Artistic License
or the GNU General Public License, which may be found in the Perl 5
source kit.
Complete documentation for Perl, including FAQ lists, should be found
on this system using `man perl' or `perldoc perl'. If you have access
to the Internet, point your browser at http://www.perl.com/, the Perl
Home Page.Hello, world!
I'm not sure who originated the practice, but far be it from me
to violate it. If you want to modify the following instructions to
make your first Perl script say Hello, sailor! or
Hey, bignose! or something else you find equally
(or probably more) amusing, go right ahead.
pico
text editor. (If your Unix server does
not have pico available, you will probably need to
look into using emacs or vi;
see Chapter 1.) If you want to write the script on
your local PC or Mac, that's fine, too; just remember that
you'll have to upload it to the Unix server via FTP (ASCII
upload, please) before you can test it.
pico by entering the command
pico in the Unix shell (clever, eh?). There are
some special features of pico you can turn on with
command-line options, and we'll be using three of them:
-d (which makes
your keyboard's Delete key erase the character under your
cursor, rather than the character to the cursor's left),
-w (which turns off automatic word wrapping), and
-z (which allows you to
suspend the pico program by
typing Ctrl-Z; more about that later).
pico's command-line options
merged together with a single leading hyphen
(-dwz), older versions of pico
may require you to enter them separately, as -d -w
-z.
pico -dwz hello.plx
at the command line. This begins your pico editing
session, with your cursor at the beginning of a new file called
hello.plx:
[jbc@andros jbc]$ pico -dwz hello.plx
.plx filename extensions to my
Perl scripts, even on Unix machines, where the filename extension has
no formal significance (unlike on DOS/Windows machines, where it is
used to indicate the file's type). This is a legacy of my
originally learning Perl on a DOS computer. I left the extension on
in these examples for two reasons:
hello.plx) all by itself. Or you may need to
precede its name by a period and a forward slash
(./). What decides this is whether the dot
(.), which you will recall is a shortcut for the
current working directory (meaning the directory you are currently
in), is in your command path.
hello.plx by itself at the shell prompt
will not work because the Unix shell will not be able to find the
script, even though it's right there. Instead, you'll
have to enter ./hello.plx, with that initial dot
slash (./) telling the Unix
shell to look in the current working directory for the command whose
name you're typing in.
./ before your
program's name can actually be a good thing because it makes it
less likely that you will accidentally run a different program with
the same name in some other directory that is in your command path.
printenv
command, as follows:
[jbc@andros jbc]$ printenv PATH
/usr/local/bin:/bin:/usr/bin:/usr/sbin:.
printenv
command, you can also try using the
echo
command to
display the contents of the $PATH shell variable:
[jbc@andros jbc]$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/sbin:.
[jbc@andros jbc]$ hello.plx
hello.plx: Permission denied.
[jbc@andros jbc]$ chmod 700 hello.plx
ls -l
filename, with
filename being replaced by the name of the
file. To look at the permissions on my hello.plx
script:
[jbc@andros jbc]$ ls -l hello.plx
-rw-r--r-- 1 jbc jbc 42 Sep 5 06:55 hello.plx
ls -l listing (the
-rw-r--r-- part) is what tells you what
permissions the file has. That -rw-r--r-- thing
can be decoded as follows:
- means it's a
file rather than a
directory or a link (see
Figure 2-2).
hello.plx executable by its
owner, let's try running it again:
[jbc@andros jbc]$ hello.plx
Hello, world!
perldebtut man page is a good
place to talk about the official Perl documentation. There is a very
complete set of documentation that comes free with Perl. If everyone
was tied down and forced to read every word of it, we'd all
know a lot more about Perl.
man
perl at the Unix command
line. If you are on a system that doesn't have the
man command (for example, because you installed
Perl locally on your PC or Mac), you can use a utility called
perldoc that comes bundled with Perl by entering
perldoc
perl. (Also, the
ActiveState version of Perl installs the Perl documentation as HTML
pages accessible under the Start menu.)
man
sectionname or perldoc
sectionname. More about this, including
the list of section names, in that first man perl
page.
perl, perlfaq,
perltoc, perldata,
perlsyn, perlop,
perlre, perlrun, and
perlfunc. The others are useful, too; it's
just that you probably will need to learn some more before you can
get much out of them.
perldoc: If you enter perldoc
-f, followed by the name of a particular Perl function, you
will get the part of the perlfunc manpage that
describes that function. For example:
print statement
in your "Hello, world!" script with
the following:
$greeting = "What are you looking at?\n"; print $greeting;
=). Then
we feed the variable (called $greeting) to the
print function.
$) are used to store a single something: a single
number or a single string of text. Programmers call these
single-something containers scalar variables.
"this is a double-quoted string"). In fact, Perl
also supports the use of single quotes (as in,
'this is a single-quoted string'). It's
important for you to understand the difference between the two.
\) and replaces them with special characters. The
sequences are called
backslash
escapes, and the process of replacing them with special
characters is called backslash interpretation.
\', which it interprets as a
literal single quote, and \\, which it interprets
as a literal backslash. This lets you put literal single quotes and
literal backslashes inside your string, which would otherwise be
difficult to do.)
quotes.plx
(Example 2-2) to see how this works.
#!/usr/bin/perl # quotes.plx -- test handling of single- and double-quoted strings $veggies = 'rutabagas'; print "I like to eat $veggies.\n";
[jbc@andros jbc]$ quotes.plx
I like to eat rutabagas.
print 'I like to eat $veggies.\n';
[jbc@andros jbc]$ quotes.plxhello.plx so that it will run
as a CGI script. Every CGI script needs to output a CGI
header
as the first thing the script outputs.
This header, which consists of one or more lines of text followed
immediately by a blank line, is checked by the web server, then
passed on to the remote user's browser in order to tell that
browser what type of document to expect. Most of the time, your
script is going to output an HTML document, which means you'll
need to output your script's header using something like the
following snippet of Perl:
print "Content-type: text/html\n"; print "\n";
foreach loops, if blocks, and
how Perl evaluates conditional statements for "truth." I
also touch on how to open a pipe to another program and print output
to that program, as well as how to use the die
function to make your script stop dead in its tracks if it notices
something unusual happening.
CGI.pm module, for example. Don't worry,
though. We'll be covering them more thoroughly in the chapters
ahead.
CGI.pm. CGI.pm
is a Perl module
,
which is basically a chunk of prewritten Perl code that you can pull
into your script to do lots of useful magic.
CGI.pm, as you might guess, is a module
specifically designed to do CGI sorts of things. It was created by
Lincoln Stein, one of the real heroes of the
Perl community, especially for anyone who uses Perl for web work. In
this script, we'll be using CGI.pm primarily
to decode data submitted from an HTML form. Although it's
possible to do that form decoding without using
CGI.pm, I encourage you not to try to do that. See Using CGI.pm Versus Manual Form Decoding for an
explanation.
CGI.pm. CGI.pm
is a Perl module
,
which is basically a chunk of prewritten Perl code that you can pull
into your script to do lots of useful magic.
CGI.pm, as you might guess, is a module
specifically designed to do CGI sorts of things. It was created by
Lincoln Stein, one of the real heroes of the
Perl community, especially for anyone who uses Perl for web work. In
this script, we'll be using CGI.pm primarily
to decode data submitted from an HTML form. Although it's
possible to do that form decoding without using
CGI.pm, I encourage you not to try to do that. See Using CGI.pm Versus Manual Form Decoding for an
explanation.
CGI.pm not only
to process the output of HTML forms, but to actually produce those
forms in the first place. With this approach, you just send a user to
your CGI script, and the first time the user invokes the script it
delivers an HTML form with all the values set to their defaults.
Then, when the form is submitted back to the same script, it takes
the data supplied by the user and does whatever you want it to do.
CGI.pm has lots of nifty features like that, but
they tend to be a bit overwhelming for beginners, so in this case
we're going to take a more straightforward approach and simply
create our form as a standard HTML page, then submit it to our CGI
script for processing.
http://www.elanus.net/book/.Or you can just
create your own copy of it.
<HTML> <HEAD> <TITLE>Sample Form</TITLE> </HEAD> <BODY> <H1>Sample Form</H1> <P>Please fill out this form and submit it. Thank you.</P> <FORM ACTION="mail_form.cgi" METHOD="POST"> <TABLE> <TR> <TD ALIGN="right"><STRONG>My name:</STRONG></TD> <TD><INPUT NAME="name" SIZE=30></TD> </TR> <TR> <TD ALIGN="right"><STRONG>Address:</STRONG></TD> <TD><INPUT NAME="address" SIZE=30></TD> </TR> <TR> <TD ALIGN="right"><STRONG>City:</STRONG></TD> <TD><INPUT NAME="city" SIZE=30></TD> </TR> <TR> <TD ALIGN="right"><STRONG>State:</STRONG></TD> <TD><INPUT NAME="state" SIZE=2></TD> </TR> <TR> <TD ALIGN="right"><STRONG>Zip:</STRONG></TD> <TD><INPUT NAME="zip" SIZE=10></TD> </TR> <TR> <TD ALIGN="right"><STRONG>Country:</STRONG></TD> <TD><INPUT NAME="country" SIZE=10 VALUE="USA"></TD> </TR> <TR> <TD ALIGN="right"><STRONG>My email:</STRONG></TD> <TD><INPUT NAME="email" SIZE=30></TD> </TR> <TR> <TD ALIGN="right"><STRONG>My favorite color: </STRONG></TD> <TD> <TABLE BGCOLOR="#CCCCFF" BORDER><TR><TD> <TABLE> <TR> <TD><INPUT NAME="color" TYPE="radio" VALUE="red"> </TD> <TD>Red</TD> </TR> <TR> <TD><INPUT NAME="color" TYPE="radio" VALUE="green"> </TD> <TD>Green</TD> </TR> <TR> <TD><INPUT NAME="color" TYPE="radio" VALUE="blue"> </TD> <TD>Blue</TD> </TR> </TABLE> </TD></TR></TABLE> </TD> </TR> <TR> <TD ALIGN="right"><STRONG>Movies I liked:</STRONG> </TD> <TD> <TABLE BGCOLOR="#CCCCFF" BORDER><TR><TD> <TABLE> <TR> <TD><INPUT NAME="movies" TYPE="checkbox" VALUE="Blade Runner"></TD> <TD><EM>Blade Runner</EM></TD> </TR> <TR> <TD><INPUT NAME="movies" TYPE="checkbox" VALUE="Pulp Fiction"></TD> <TD><EM>Pulp Fiction</EM></TD> </TR> <TR> <TD><INPUT NAME="movies" TYPE="checkbox" VALUE="Full Metal Jacket"></TD> <TD><EM>Full Metal Jacket</EM></TD> </TR> </TABLE> </TD></TR></TABLE> </TD> </TR> <TR> <TD ALIGN="right"><STRONG>When I grow up I want to be a(n):</STRONG></TD> <TD> <SELECT NAME="grow_up"> <OPTION>Astronaut <OPTION>Fireman <OPTION>CGI programmer </SELECT> </TD> </TR> <TR> <TD ALIGN="right"><STRONG>My opinion on cucumber sandwiches is:</STRONG></TD> <TD> <TEXTAREA NAME="sandwiches" ROWS=5 COLS=20 WRAP="virtual"> </TEXTAREA> </TD> </TR> <TR><TD COLSPAN=2> </TD></TR> <TR> <TD> </TD> <TD><INPUT TYPE="submit"> <INPUT TYPE="reset"> </TD> </TR> </TABLE> </FORM> </BODY> </HTML>
ACTION
attribute of the <FORM> tag. In the previous
example page, the form is handed off to a script called
mail_form.cgi located in the same directory as the
form itself.
ACTION attribute and handed the form off to a
script in a different directory. You could even have given a full URL
(http://www.somewhere.com/somepath/somescript.cgi)
and handed the form's contents off to a script on a completely
different server. But I'm digressing. The point is, the
ACTION attribute of the
<FORM> tag is what determines where the form
data goes when the form is submitted.
http://www.elanus.net/book, and
stick it in a suitable location on your web server. If you can
execute CGI scripts anywhere, you can stick it in the same directory
as your HTML form. If you need to put your scripts in a special
location, stick it there, and then be sure to modify the
ACTION attribute of the
<FORM> tag to point to it properly. For
example, if you needed to put the script in a top-level directory on
your server called cgi-bin, you would edit the
<FORM> tag to read: <FORM
ACTION="/cgi-bin/mail_form.cgi" METHOD="POST">.
#!/usr/bin/perl -w
# mail_form.cgi
# bundle up form output and mail it to the specified address
# configuration:
$sendmail = '/usr/sbin/sendmail'; # where is sendmail?
$recipient = 'forms@example.com'; # who gets the form data?
$sender = 'forms@example.com'; # default sender?
$site_name = 'my site'; # name of site to return to after
$site_url = '/return/path/here/'; # URL to return to after
# script proper begins...
use CGI qw(:standard);
# bundle up form submissions into a mail_body
$mail_body = '';
foreach $field (param) {
foreach $value (param($field)) {
$mail_body .= "$field: $value\n";
}
}
# set an appropriate From: address
if ($email = param('email')) {
# the user supplied an email address
$email =~ s/\n/ /g;
$sender = $email;
}
# send the email message
open MAIL, "|$sendmail -oi -t" or die "Can't open pipe to $sendmail: $!\n";
print MAIL <<"EOF";
To: $recipient
From: $sender
Subject: Sample Web Form Submission
$mail_body
EOF
close MAIL or die "Can't close pipe to $sendmail: $!\n";
# now show the thank-you screen
print header, <<"EOF";
<HTML>
<HEAD>
<TITLE>Thank you</TITLE>
</HEAD>
<BODY>
<H1>Thank you</H1>
<P>Thank you for your form submission. You will be hearing
from me shortly.</P>
<P>Return to
<A HREF="$site_url">$site_name</A>.</P>
</BODY>
</HTML>
EOF-w:
#!/usr/local/bin/perl -w
-w turns on Perl's
warnings feature, which causes the script to
complain to standard error if certain suspicious-looking things
appear to be going on. We haven't bothered with it before this,
since the other scripts so far have been so short and simple, but
this one is complex enough that it's worth turning it on.
use warnings; near the
beginning of your script instead of using the -w
shebang-line switch. If your version of Perl is recent enough to
support it, the use warnings approach has some
minor advantages over the -w switch, so you should
probably use it. In this book I'll just be using the
-w switch.
# configuration: $sendmail = '/usr/sbin/sendmail'; # where is sendmail? $recipient = 'forms@example.com'; # who gets the form data? $sender = 'forms@example.com'; # default sender? $site_name = 'My Site'; # name of site to return to after $site_url = '/~myname/'; # URL to return to after
sendmail
program
can be found. The script will use this information later on to send
the message containing the form data. Use the
which command in the shell to find out where on
your system sendmail is located (or the
whereis command, if which is
not supported on your system; see Chapter 2):
[jbc@catlow jbc]$ which sendmail
/usr/sbin/sendmail
sendmail, you can put
the full path inside the single quotes on the right side of the equal
sign to assign it to the $sendmail variable:
$sendmail = '/usr/sbin/sendmail';
$sendmail doesn't do
anything special within Perl, by the way. Perl doesn't know how
you are planning to use this variable, and just treats it as a
storage location. You could call it
$mail_program_location or
$walnuts or anything else you wanted (as long as
the variable began with a use CGI qw(:standard);
CGI.pm magic. In
effect, what you are doing with this line is adding a whole bunch of
prewritten Perl code to your script. That code arrives in the form of
some new functions that your script now has access to for doing
various CGI-related things. As I mentioned earlier, I'm not
going to explain that process in detail here. In a few minutes,
though, you'll see how easy this makes it to process the
submitted form elements received by the script.