Perl by w6WLescw



functions, pipes, and client side
perl and functions
• Perl starts at the top of scripts and executes statements
   as it finds them. functions are skipped over until they
   are called and all functions are global.
• subroutines and functions are the same thing in perl
• example
call to function;
syntax of functions
• basics
   sub helloworld {
     print "Hello World! \n";
• calling the function
• a arguments to helloworld and return values are
  ignored by this call.
• function calls have the following syntax
LIST = FunctionName (LIST);
   —() are "mostly" optional.
parameter list
• You don't "declare" the parameter to a function
  and you can send 0 or more parameters to any
• Inside a function the parameter list is located in
• example:
   sub mysub {
     my ($parm1, $parm2, $parm3) = @_;
• Call
   mysub ($val1, $val2, $val3);
parameter list
• Since perl doesn't check the parameter, it is up
  to the function
• example:
sub ex2 {
   foreach $par (@_ ) {
      print "$par \n";

@arr = (1, 2, 3, 4);
@arr = ("one", "two");
Pass by Value and Pass by Reference
• @_ is a pass by reference value
• So, changing @_ in the function changes the calling
• In the last example, @_ was copied into variables. That
  is pass by value.
• Example:
   sub mysub {
     my ($parm1, $parm2, $parm3) = @_;
     $parm1 = 2; @_[1] = 12;
• Call
   $val1 = 200; $val2 = 0; $val3 = 30;
   mysub ($val1, $val2, $val3);
   #$val1 = 200, $val2 = 12, $val3 = 30
return values
• use the return statement
sub test {
  print "Hi \n";
  return "Hi";

$v = test();

• return values can be a scalar data and lists,
  including undef (normally used for error )
scoping issues and rules
• my $var; #delcares a "private" variable
   —The scope of the variables depends on where is
   —It is local to the BLOCK it is declared in and to any
    function declared with that BLOCK.
      – NOTE: if declared outside of BLOCK, then it is global.
        functions are always declared as global.
• Example:
{ my $i = 1;
   sub iblock { print "$i\n"; } # output "1 \n"
print "$i \n"; #output " \n"
scoping issues and rules (2)
my $i = 1;
   sub iblock { print "$i \n";} #prints 1
print "$i \n"; #prints 1
• Note the difference here.
print "$i \n"; #prints "\n"
{my $i = 1;
   sub iblock { print "$i \n";} #prints "\n"
• $i has not be declared yet, since my $i has not executed
   until after the print statement.
my vs local
• my declares a variable private to it's block (or
   global if there is no block)
• local takes a global variable and gives it a
   temporary value for the block it is was
   "declared" in.
• example:
$i = 1;
print "$i \n"; #output "1 \n";
{ local $i =2;
   print "$i \n"; #output "2 \n";
print "$i \n"; #output "1 \n";
my vs local (2)
{ #take the global variable $/ (read marker for file) and set it to undef
   inside the block.
   local $/;
   $_ = <FILEHANDLE>;
sub test { print "$i \n";}
test(); #output "1 \n";
{ local $i=2;
   test(); #output "2 \n";
Exercise 12
• Using the grading program from previous
• Write a function that determines the grade
  based on the numerical value. It will return the
  letter grade.
• The "main" code calls the function with a
  numerical grade and print the letter grade.
built-in functions
• file system functions
  —chmod LIST such as chmod 755 'file1';
  —opendir, readdir, closedir
  —opendir(DIRHANDLE, NAME); #like file open, but for
     – opendir(THISDIR, ".");
  —LIST = readdir DIRHANDLE;
     – @allfiles = readdir THISDIR; #all the filesnames are put in
     – $nextfile = readdir THISDIR;#the next filename is put in
  —closedir DIRHANDLE;
     – close THISDIR;
built-in functions (2)
  —do FILE; # executes the contents of the file as a Perl
     – do '';
  —chdir DIRECTORY #change current working directory
     – chdir "/usr/local/"; #change to /usr/local
     – chdir; #change to user home directory
  —mkdir FILENAME [, MASK]
     – mkdir "dir";
  —rmdir FILENAME;
     – rmdir "dir"; #if the directory is empty
  —unlink FILENAME; #deletes the FILENAME
     – unlink "filename";
built-in functions (3)
• file test (operators)
   -e "file"   true   if   "file" exists
   -r "file"   true   if   "file" is readable
   -w "file"   true   if   "file" is writable
   -d "dir"    true   if   "dir" is a directory
   -T "file"   true   if   "file" is a text file
       – Not a binary file
   -f "file"   true if "file is a regular file
       – Not a directory, device file, etc.
• Examples:
if ( -e "filename") { print "filename exists";}
-r $file and open FP, $file;
Walking a filesystem
use Cwd; # module for finding the current working directory

sub WalkDir{
    my ($workdir) = shift;# or shift @_;
    my ($startdir) = cwd(); # keep track of where we began
    if (-r $workdir) { print "$startdir/$workdir \n"; }
    else { print "Unable to enter $startdir/$workdir \n"; return; }

    chdir($workdir) or die "Unable to enter dir $startdir $workdir:$!\n";
    opendir(DIR, ".") or die "Unable to open $workdir:$!\n";
    my @names = readdir(DIR) or die "Unable to read $workdir:$!\n";

    foreach my $name (@names){
        next if ($name eq "."); #current directory
        next if ($name eq ".."); #parent directory
        next if (-l $name); #linked file or directory, next
        if (-d $name){ # is this a directory?
        #you could process files here if you want. example: delete core files
        # if ($name eq "core") { unlink ($name) }
    chdir($startdir) or die "Unable to change to dir $startdir:$!\n";

built-in functions (4)
• time functions
  —time; #returns the number of nonleap seconds since
   "The epoch"
     – UNIX since Jan 1, 1970 00:00:00 UTC
  —gmtime; returns as greenwich time zone
     – ($sec, $min, $hour, $mday,
       $mon,$year,$wday,$yday,$isdst) = gmtime;
     – ($min,$hour) = gmtime[1,2];
  —localtime; returns the local time zone
     – ($sec, $min, $hour, $mday,
       $mon,$year,$wday,$yday,$isdst) = localtime;
     – ($min,$hour) = localtime[1,2];
  —NOTE: months 0 through 11, instead of 1 – 12
         and year is starts at 1900, so 2002 is 102
     – so $year += 1900; $month++; #for corrections.
built-in functions (5)
• couple other functions
  —srand [EXPR]; #seeds random number generator
  —rand; #returns a floating-point number from 0 to 1
   (excluding 1)
     – rand EXPR; #return a floating-point number from 0 to EXPR
       (excluding EXPR)
  —sleep EXPR;
     – puts the script to sleep for EXPR seconds
     – return how many sleeps the script slept.
  —$x = system("COMMAND");
     – system("rm –rf /tmp/*"); #execute the command specified.
       output is not returned to the script.
built-in functions (6)
• back quotes
  —perl will execute a command (passing command to
   the shell/DOS prompt to be executed).
  —The output of the command is returned.
     – $returnoutput = `command`;
     – @outputarr = `command`;
  —$out = `ls -la`; # for UNIX
  —$out = `dir`; # for windows
     – for both, output is return to $out, newline between each line
       out put from the command.
  —@arr = `dir`; #or @arr= `ls –la`;
     – Each line is placed in an array element (starting at 0)
Unix built-in functions
• Access to the password file (even shadow
  password file and NIS passwords)
  —Perl has a number of function for sysadmin on UNIX
     – returns username for uid number
     – return uid number for the usename
  —Each return an array when set to an array value
     – ($usrname, $passwd, $uid, $gid, $quota, $comment, $gcos,
       $dir, $shell) = getpwnam("seker");
     – For on the home home directory
     – $dir = (getpwnam("seker"))[7];
Unix built-in functions (2)
• To access and process the entire "password" file
      – initialize access to the "password file"
   —@list = getpwent();
      – fetch next entry of password file
      – returns undef, for end of file.
      – "close" password file.
• For the "group file"
   —getgrgid(id) and getgrnam("string")
      – get group id (returns name) and get group name (returns id)
   —setgrent, getgrent, and endgrent
      – like processing pasword file
      – return an array ($name, $passwd, $gid, $members)
Unix built-in functions (3)
• There are others. With the open, system, and
  backquote commands, most UNIX admin can be
  handled easily.

• I'll cover windows admin functions (win32
  module) in lecture 7
Interprocess Communication
  —Two or more processes communicating
  —The processes must agree on a common protocol

• We'll cover process concurrency, pipes, and
  client network sockets.
  —next lecture, server side network sockets.
Process Concurrency
• fork command
   — The fork command creates a child process, which is duplicate
     copy of the parent process.
      – Duplicates all resources and data
• Example:
$a = 12;
if ($pid = fork) {
# Parent process
  print "Parent: a = $a\n";
  wait; #wait for the child process to end
} elsif (defined $pid) { #$pid contains 0
#child process
  print "Child: a = $a\n";
} else { #fork failed
  die "Can't fork: $! \n";
Process Concurrency (2)
• In older versions of perl, win32 machines had to
  use perlfork.
• Use fork very carefully, a "out of control" fork
  can cause systems to crash.
  —such as the parent and children process both
   continue to fork.
  —The parent process should always use the wait
   command for child process. Child processes on exit
   return information to the parent process. If the child
   process is unable to do so, it can be left as zombie
   process (a process attempting to terminate, but
   unable to).
• We've looked at pipes with the open command.
  But we were unable to use two way
  —allows two related processes to talk to each other.
  —With one pipe, 1 process is the reader, the other is
   the writer (doesn't matter which one, so long as the
   roles are known.)
  —With two pipes, you have two way communication.
     – Process 1 reads on one pipe and writes to the second.
     – Process 2 reads on the second pipe and writes to the first.
• We also use the autoflush command (in the
  IO::Handle module), so data does not get
  "stuck" in a pipe.
one way pipe example
use IO::Handle;

if ($pid = fork) {
# Parent process
  print WRITER "HI\n";
  waitpid($pid,0); #wait for the child process to end.
} elsif (defined $pid) { #$pid contains 0
#child process
  chomp($line = <READER>);
  print "Child: $line \n";
} else { #fork failed
  die "Can't fork: $! \n";
close READER;
close WRITER;
Two way pipes example
use IO::Handle;
pipe(CREADER,PWRITER); #create pipe 1 child reads from, parent writes to.
pipe(PREADER,CWRITER); #create pipe 2 parent reads from, child writes to.

if ($pid = fork) {
# Parent process
  print PWRITER "Hi child\n";
  chomp($line = <PREADER>);
  print "Parent: $line \n";
  waitpid($pid,0); #wait for the child process to end.
} elsif (defined $pid) { #$pid contains 0
#child process
  print CWRITER "Hi parent\n";
  chomp($line = <CREADER>);
  print "Child: $line \n";
} else { #fork failed
  die "Can't fork: $! \n";
close CREADER; close PREADER;
close CWRITER; close PWRITER;
two way communication
• Opening two pipes is complicated. To make it
  simpler, we can open a socket-pair instead.
  —NOTE: socket-pair function is broken in ActivePerl
• Uses the Socket module
  —More on the Socket module later on.

• Eliminates the need for multiple pipes.
  —The parent uses the CHILD to read and write
  —The child uses the PARENT to read and write
     – think of "reading from the PARENT" and "writing to the
Socket-pair example
use Socket;
use IO::Handle;
if ($pid = fork) {
#parent code
  print CHILD "Hi from Parent\n";
  chomp($line = <CHILD>);
  print "Parent: $line\n";
  close CHILD; close PARENT;
} else {
  die "cannot fork: $!" unless defined $pid;
#child code
  chomp($line = <PARENT>);
  print "Child: $line \n";
  print PARENT "Hi back from child\n";
  close CHILD; close PARENT;
Network Sockets
• Some quick definitions
   — Server: Offers it's services and "listens" for a request
   — Client: Requests services from a server by initiating a
     "connection" to the server.
   — Socket (refers both the Sockets API and a communication
      – stream (SOCK_STREAM), which provide a bidirectional, sequenced,
        and reliable channel of communication
          + Used in major network applications
          + TCP connection
      – datagram (SOCK_DGRAM), which do not guarantee sequenced or
        reliable delivery, but are lightweight
          + Used as broadcast applications, and "steaming video/audio"
          + Think about as radio or TV
          + UDP connection
      – Port numbers are used to determine which program you want to
        talk to. Web servers usually use port 80, mail port 25, ftp port 23.
        RFC 1700 lists well know port numbers.
Network Sockets(2)
• There are two modules used to make a
• IO::Socket or Socket modules
  —IO::Socket is simpler of the two to establish a
   network connection
  —Socket allows more control over the creation of the

• Both create a connection to remote machine via
  a socket.
IO::Socket module
• IO::Socket for a client connection
   — $socket = IO::Socket::INET->new (PeerAddr => $remote_host,
     PeerPort => $remote_port, Proto => "tcp", Type =>
     or die "Couldn't connect to $remove_host:$remote_port :
   — PeerAddr => $remote_host
      – Where $remote_host is either a IP address or Name, such as or
   — PeerPort => $remote_port
      – Where $remote_port is a port number, such port 80 (http port),
        port 25 (smtp port), etc
   — Proto => "tcp", Type => SOCK_STREAM
      – Connection type
      – OR Proto => "udp", Type => SOCK_DGRAM
      – If these two parameters are left off, the default is "tcp",
IO::Socket module (2)
• Once it's open use the $socket variable as you
  would a FILEHANDLE to read and write the
• sending:
  —print $socket "bah… bah…\n";
• Receiving
  —$line = <$socket>;
• To close the connection
  —close ($socket);
IO::socket client example
use IO::Socket;
#Read the index page from asuwlink's web server
$remote_host = "";
$remote_port = "80";
$socket = IO::Socket::INET->new (PeerAddr =>
  $remote_host, PeerPort => $remote_port, Proto =>
  "tcp", Type => SOCK_STREAM)
  or die "Couldn't connect to
  $remote_host:$remote_port : $@\n";
print $socket "GET / HTTP/1.0\n\n"; #http protocol
  #normally, we would write the next line.
  local $/; #http sends entire file, then closes
  connection, so we'll just read the entire file
  $answer = <$socket>;
  print "$answer \n";
close $socket
Socket module
• More complex and multi stepped.
• create a socket to use
  —PF_INET it the domain type, with IO::Socket it was
   part of the new call.
  —getprotobyname('tcp') get the O/S number for tcp
     – should allows use this function, since the number has been
       known to change and for portability issues.
Socket module (2)
• Next build address of remote machine
$internet_addr = inet_aton($remote_host);
$paddr = sockaddr_in($remote_port, $internet_addr);
   — inet_aton function converts IP number/name to machine usable
   — sockaddr_in for PF_INET function (socket_un for PF_UNIX)
     "packs" the port and name together to form a remote socket
• Now connect to remote machine
connect(SERVER, $paddr);
• SERVER is the handle to use for read/writing to
  server, same as IO::Socket $socket
Socket client example
use Socket;
use IO::Handle;

$remote_host = "";
$remote_port = 80;
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
SERVER->autoflush(1); #socket doesn't have autoflush turned on.
$internet_addr = inet_aton($remote_host) or die "Can't convert $!\n";

$paddr = sockaddr_in($remote_port, $internet_addr);
connect (SERVER, $paddr) or die "can't connect $!\n";

print SERVER "GET / HTTP/1.0\n\n",$flags;
{ local $/; #again, same thing, normally won't set this.
$answer = <SERVER>;
print "$answer \n";
close SERVER;
Exercise 13
• Write a client app to connect to a remote
  machine. Use machine name giving to you as
  the host and port 3012

• It should send the message "Connection from
• and then wait for a response and print the
  response to STDOUT

To top