Jan. 12, 2000
_____________________________________________________________________
See the Happy Hacker web site at http://www.happyhacker.org
Firewall gives you problems? Try http://happyhacker.org
______________________________________________________________________
***********************************************************************
*** Editor's Comments
***********************************************************************
Once again, the Unix Digest is here. For some reason, it seems
there were
fewer letters this week. If this is because less people had problems,
great!
If not... well... don't be shy... write in! Ok? In addition,
if anyone is
located in NYC, and wants Debian CD's, let me know by email,
and we can work
something out.
***********************************************************************
*** Readers' Submissions
***********************************************************************
matt morgan <neptune2002@hotmail.com> wrote:
I would like to know whether a tcsh prompt is configurable
and how to configure it
I have been told that a "set prompt=" in .cshrc
might work
but I am having no luck finding someone that actively uses tcsh
also there are no man pages for tcsh on my computer
[Editor: Yes. As far as how... I'd suggest you first try a
search on your
favorite search engine.]
-----------------------------------------------------------------------
pyromaniac <pyromanic@kmfms.com> sent in:
Hi !
the next month, I get a new internet connection. radiolink at
2 mbit, very
cheap ! :)
I want to share this connection with one of my neighbours, who
is a very
good friend of mine.
we have, together, 7 computers, most of them running Linux or
windows
98/2000.
I will use one old 486 as a server, which I connect to the 'net.
this server will be running the Debian Linux dist.
what I don't really understand is what do I have to do for the
linux
machine to act as a server, how do i connect to it from one of
the win
machines, and what setup do i have to do in linux ?
thanx in advance
pyromanic [ pyromanic@kmfms.com ]
[Editor: Ok, I'm glad to hear you're running Debian, which
is, of course,
the best linux distro out there :). Seriously, excellent question.
What
you'd probabaly want to do is first set up your internal network.
The debian
install is very thorough on setting up a network, though you
should
definately make sure to read the HOWTO on setting up networks.
The easiest
way to set up 'net access would probabaly be by using IP Masquarading.
I
used to be quite proficient with IPMasq, although I haven't used
it
recently, and I doubt I remember all of the setup options. Read
IPMasq
(mini???)HOWTO, it covers many examples in full detail. And enjoy
:).]
-----------------------------------------------------------------------
Mike Miller <unixeditor@cmeinel.com> says:
Your question here! Just send email to unixeditor@cmeinel.com.
***********************************************************************
*** Perl 101, Lesson 3
***********************************************************************
Sorry about last week... I had a ton of finals, and at 20K/year,
I have to
put my college before this newsletter. I'm off now, and there'll
be a full
article this time, so open up another terminal, and start up
vi (or your
favorite editor), and let's rock and roll (as much as you can
rock and roll
with perl :) ).
First topic: subroutines. Previous programmers should already
be familiar
with the concept of a subroutine (a.k.a. procedure a.k.a. function...
yes, I
do know there is actually a difference... don't worry about it
for now). To
the newbies, a subroutine is a small part of a program that performs
a task.
What good is this? Let's take a general program. This program
takes input,
does something, returns output. Sounds pretty typical, right?
So why not
write the program like this (pseudo-code)
Main Program:
Get Input
Process
Return Output
Nice and simple. Hey, the program could be as short as 5 lines.
But how does
the computer know how to "Get Input"? In comes the
subroutine. We could
create subroutines to accomplish each of these tasks. The advantages
should
be obvious: reusability, modularity, and simplicity. Enough philosophy,
let's see how to write a subroutine. First, we need a reason.
Well, here's
one. On our original program, we had a procedure for checking
for "earth" in
any case (we used the regular expression /earth/i instead of
the string
"Earth", and we used the binding operator =~ (thanks
darkm00n`) instead of
eq, but when we went to a hash lookup, we couldn't do that, because
then
$planethash($index) was a string, not a regular expression. So
let's try
rearranging the input so it's converted to lowercase, then we
can compare it
with a string of all lowercase names in %planethash. In other
words, instead
of comparing "Earth" or "earth" or even "EaRtH"
with "earth", we'll take
every string, make all it's letters lower case, and then we can
do a string
comparison (an eq test). First, we'll write that, then we'll
create a
subroutine call planet_parse that will contain all the code to
parse (i.e.,
process) the input until it's ready for the comparison. Here's
the code to
make the change:
$planetname =~ tr/A-Z/a-z/; #yes, I'm aware of the uc function...
but this
is an R/E.
The tr/RE1/RE2/ operator, similar to the slash replacement
command from many
editors, replaces every element in RE1 with RE2. So in our example,
every
letter in the 26 element array of letters from A to Z will be
replaced with
it's analogue (i.e., same index number) in the array of a to
z. And the =~
operator binds (assigns) the value on the right to that on the
left. I
admit, a simple line does not require a subroutine. Actually,
to use a
subroutine would be remarkably inefficient, but there could be
a lot of
processing code, so we'll create a framework.
sub planet_parse
{
my($planettemp) = @_;
$planettemp =~ tr/A-Z/a-z/;
return $planettemp
}
This is very poor coding. But before we explain why you shouldn't
do this,
let's see what happens. The my creates a local variable (i.e.,
it does not
"exist" outside of this subroutine, without it, we'd
make a global variable
(which could be accessed anywhere in the program). The @_ is
a special array
which (in this case) will contain the parameters passed to the
subroutine.
All subroutines have two things associated with them... input
(a.k.a.
parameters) and output. When we call the planet_parse subroutine,
we'll give
it a parameter, the variable we're using to contain the planetname
(coincidently enough, $planetname). The tr/ statement we already
explained,
and the return statements tells the subroutine what to send back.
If there
is not return statement, the subroutine will return the value
of the last
statement. Thus, in this case, we could leave off the return
statement, and
since $planettemp =~ tr/A-Z/a-z/; evaluates to $planettemp, it
would be
sufficient. Usually the return statement is used in conjuction
with an
if-elsif-else framework to return a varying output. An utterly
useless
subroutine, but it makes the point.
But what do we do with this? Try the following:
#!/usr/bin/perl
%planethash=(
"Mercury", "Hi Merc. Are you related to Merck
Chemical? Haha!",
"Venus", "Ever met John Gray?",
"Earth", "Third Rock, eh?"
"Mars", "Ever met John Gray?",
"Jupitar", "Do you really jump?",
"Saturn", "Sega!",
"Uranus", "I think you know the joke...",
"Neptune", "Nothing interesting to say about you.
Sorry, pal."
"Pluto", "Have you sued Walt for copyright infringement?");
sub planet_parse
{
my($planettemp) = @_;
$planettemp =~ tr/A-Z/a-z/;
return $planettemp
}
#main program begins here
print("What do you call your planet? ");
$planetname = <STDIN>;
chomp($planetname);
$output = (%planethash(planet_parse($planetname)) || "Hi.
Where exactly is
that located?");
print ($output, "\n");
}
Seems pretty straightforward. The subroutine returns a value
(in this case,
a scalar variable), so it can be used in place of a value. I
presume you
know the || expression (if not... it means logical OR, but you
knew that,
right?). Note that unlike certain other languages, if the first
part of an
OR statement evaluates to something other than ""/undef/NULL,
the second
term is not evaluated at all.
Ok, that covers basic subroutining. Let's see... disk I/O.
The key to understand disk I/O is to know that it's no different
than taking
data in from the keyboard. Just like data comes from the keyboard
in the
<STDIN> handle (or from a pipe, whatever), disk files can
be read from by
using a handle. To do this, use the open function.
open (PLANETHANDLE, "/usr/local/lib/planetfile")
Assuming that there was such a file (you can test by making
sure
PLANETHANDLE is defined), you could read from it by saying:
$planetname=<PLANETHANDLE>
That's it. Of course, there are a lot more things you can
do with I/O, but
that's basically how to take a file, and treat it as though it
came STDIN.
Caveat: When working with STDIN, not much can go wrong (it's
pretty hard to
not have a STDIN). But it's quite possible a file doesn't exist,
or (and
this will almost always be an issue) maybe you reached the end
of the file.
The key is that both the $variable=<HANDLE> and open statements
will return
undef under these conditions. So use the defined function (returns
FALSE iff
the input equals undef) as follows
if (defined(open(PLANETHANDLE,"/usr/local/lib/planetfile")))
{
<next block>
}
That way, the code will only be executed if the open worked.
You can use a
similar technique to determine when you've reached the end of
the file (put
your read statements inside a while loop). That should do it
for this
week... Happy Perl-ing!
-----------------------------------------------------------------------