Previous Page Next Page

18.3. Other Ways to Interface with the Operating System

If the system functions are still not enough, Perl offers a number of alternative ways to deal with the operating system. You can use the syscall function, command substitution, the system function, and the here document to get system information.

18.3.1. The syscall Function and the h2ph Script

The syscall function calls a specified system call with its arguments. If the C system call is not implemented, a fatal error is returned. The first argument is the name of the system call, preceded by &SYS_. The remaining arguments are the actual parameters that are required by the real system call. If the argument is numeric, it is passed as a C integer. If not, the pointer to the string value is passed. You may have to coerce a number to an integer by adding 0 to it if it is not a literal and cannot be interpreted by context.

Before using the syscall function, you should run a script called h2ph (h2ph.bat on Windows) that comes with the Perl distribution. At the bottom of the h2ph script (after _ _END_ _) are the manual pages for h2ph, including an explanation on how to run the script. This script converts the proper C header files to the corresponding Perl header files. These files must be added to the Perl library if you are using functions that require them. All the files created have the .ph extension. After running the h2ph script, make sure that the @INC array in your program includes the path to these library functions.[12]

[12] See also the h2xs script that comes with Perl 5 distribution, for building a Perl extension from any C header file.

Format

syscall (&SYS_NAME, LIST);

Example 18.57.

(UNIX: At the Command Line)
1   $ cd /usr/include; /usr/local/bin/perl/h2ph * sys/*

(In Script)
    #!/bin/perl
    # The name of the script is args.p
2   push(@INC, "/usr/local/lib");
3   require "syscall.ph";
4   $bytes=syscall(&SYS_getpagesize);
5   printf "The pagesize for this Sparc Sun Workstation is %d
           bytes \n",$bytes;

(Output)
5   The pagesize for this Sparc Sun Workstation is 4096 bytes.

Explanation

  1. h2ph is executed so that the necessary C header files are converted to Perl header files. The files created will be placed in /usr/local/lib and end with a .ph extension.

  2. The directory containing the .ph files is pushed onto the @INC array.

  3. The file syscall.ph is required for using C system calls.

  4. The Perl syscall function will call the getpagesize system call. The prefix &SYS_ is necessary Perl syntax. It must be prepended to the real system call name.

  5. The page size for this Sun4c is 4,096 bytes.


18.3.2. Command Substitution—The Backquotes

Although we have already discussed command substitution and backquotes in Chapter 5, "What's in a Name," a quick review might be in order here because command substitution is yet another way for Perl to interface with operating system commands.

Backquotes are used by the UNIX/Linux shells (not Windows) to perform command substitution and are implemented in Perl scripts pretty much the same way. For example, the command line echo The present working directory is 'pwd' will cause the command in backquotes to be executed and its results substituted into the string. Like the UNIX/Linux shell, enclosing a command in backquotes causes it to be executed. Unlike the shell, if double quotes surround the backquoted string, command substitution will not occur. The output resulting from executing the command is saved in a scalar variable.

Example 18.58.

(The Script)
    #!/bin/perl
1   print "The hour is ",'date';

2   @d='date';
3   print $d[0]'

4   @d=split(/ /,'date');
5   print "$d[0]\n"
6   $machine='uname -n';
7   print "$machine\n"'

(Output)
1   The hour is Thu May 31 20:47:17 PDT 2007
3   Thu May 31 20:59:11 PDT 2007
5   Thu
7   dolphin

Explanation

  1. The UNIX date command is enclosed in backquotes. It is executed and appended to the string The hour is.

  2. The array @d is set to the output of the date command. The output is stored as a single string, unlike the shells, where the output is stored as a list.

  3. Since the output of the command is stored as a single string, $d[0] is the entire string.

  4. The split command creates a list from the output returned from the date command.

  5. Now the first element of the array is the first word in the list, Thu.

  6. The scalar $machine is assigned the value of the UNIX command, uname -n, which contains the name of the host machine (hostname on BSD).

  7. The name of the host machine is printed.

18.3.3. The Shell.pm Module

This module lets you use UNIX commands that you normally type at the shell prompt in a Perl script. The commands are treated like Perl subroutines. Arguments and options are passed to the commands as a list of strings.

Example 18.59.

(The Script)
    #!/bin/perl
1   use Shell qw(pwd ls date);   # Shell commands listed
2   print "Today is ", date();
3   print "The time is ", date("+%T");
4   print "The present working directory is ", pwd;
5   $list=ls( "-aF");
6   print $list;

(Output)
2   Today is Tue May 29 13:41:56 PDT 2007
3   The time is 13:41:57
4   The present working is /home/ellie/sockets
6   ./
    ../
    sh.test*
    shellstuff
    timeclient*
    timeclient5*
    timeserver*
    timeserver5*

Explanation

  1. The Shell.pm module will be used in this program. The three UNIX shell commands pwd, ls, and date will be treated as ordinary Perl subroutines.

  2. The date command is executed as a subroutine. This is an alternative to using backquotes.

  3. Arguments passed to the date command are strings enclosed in quotes.

  4. The pwd command is executed.

  5. The output of the ls command is assigned to scalar $list. The argument is passed to the function as a single string.

  6. The output of ls -aF is a list of files in the present working directory. The -a switch includes the dot files, and the F causes the executable scripts to be marked with an asterisk (*) and the directories with a /.

18.3.4. The system Function

Like its C counterpart, the system function takes a system command as its argument, sends the command to the system shell for interpretation, and returns control back to the calling program, your script. This is just like the exec functions, except that a fork is done first, so that control is returned to the Perl script. Because it does not flush the output buffer, the special Perl variable $| is set to 1 to force a flush of the buffer after print or write statements.[13]

[13] A fork is done, the script waits for the command to be executed, and control is then returned to the script.

Format

system("system command");
system "system command";

Example 18.60.

(UNIX: The Command Line)
1   system("cal 1 2007");
    print "Happy New Year!\n";'

(Output)
    January 2007
Su  Mo  Tu  We  Th  Fr  Sa
 1   2   3   4   5   6
 7   8   9  10  11  12  13
14  15  16  17  18  19  20
21  22  23  24  25  26  27
28  29  30  31
    Happy New Year!

(Windows)
2   system("notepad.exe");

Explanation

  1. The system function executes the UNIX cal command to print out the calendar for the month of January 2007.

  2. The system function executes the Windows notebook.exe command and starts up a session of Notepad.


Example 18.61.

     (The Script)
     1   print "Hello there\n";
     2   print "The name of this machine is ";
     3   system ("uname -n"); # Buffer is not flushed
     4   print "The time is ", 'date';

     (Output)
1    Hello there
3    jody
2,4  The name of this machine is The time is Tue May 29 13:39:35 PDT 2007

Explanation

  1. The first print statement is executed as expected.

  2. Since Perl depends on the default I/O buffering mechanism, the buffer may not be flushed immediately after the print statement; the results of the system function, executed by the shell, are printed first.

  3. The system function causes the shell to execute the UNIX command uname -n.

  4. This print statement is printed directly after the print statement in line 2.

Example 18.62.

(The Script)
    #!/bin/perl
1   $|=1; # Set special variable to flush the output buffer
2   print "Hello there\n";
3   print "The name of this machine is ";
    system ("uname -n");
4   print "The time is ", 'date';

(Output)
2   Hello there
3   The name of this machine is jody
4   The time is Tue Jan 26 13:43:54 PST 2001

Explanation

  1. The $| special variable, when set to nonzero, forces the output buffer to be flushed after every write or print.

18.3.5. here documents

The Perl here document is derived from the UNIX shell here document. As in the shell, the Perl here document is a line-oriented form of quoting, requiring the << operator followed by an initial terminating string. There can be no spaces after the <<. If the terminating string is not quoted or double quoted, variable expansion is performed. If the terminating string is single quoted, variable expansion is not performed. Each line of text is inserted between the first and last terminating strings. The final terminating string must be on a line by itself, with no surrounding whitespace.

Perl, unlike the UNIX shell, does not perform command substitution (backquotes) in the text of a here document. Perl, on the other hand, does allow you to execute commands in the here document if the terminator is enclosed in backquotes.

Example 18.63.

(The Script)
    #!/bin/perl
    $price=100;
1   print <<EOF;    # No quotes around terminator EOF are same
                    # as double quotes
2   The price of $price is right.     # Variables are expanded
3   EOF
4   print <<'FINIS';
5   The price of $price is right.
                    # The variable is not expanded
                    # if terminator is enclosed in single quotes
6   FINIS

7   print << x 4;   # Prints the line 4 times
8   Christmas is coming!
        # Blank line is necessary here as terminating string

9   print <<'END';  # If terminator is in backquotes,
                    # will execute UNIX commands
10  echo hi there
11  echo -n "The time is "
12  date
13  END

(Output)
2   The price of 100 is right.
5   The price of $price is right.
8   Christmas is coming!
    Christmas is coming!
    Christmas is coming!
    Christmas is coming!
10  hi there
    The time is Fri Nov 3 17:03:46 PST 2000

					  

18.3.6. Globbing (Filename Expansion and Wildcards)

If you have worked at the UNIX or MS-DOS command line, you have been introduced to the shell metacharacters used to expand filenames. The asterisk (*) is used to match all characters in a filename, the question mark (?) to match one character in a filename, and brackets ([ ]) to match one of a set of characters in a filename. The process of expanding these shell metacharacters to a filename is called globbing.

Perl supports globbing if the filenames are placed within angle brackets, the read operators. There is also a Perl 5 function for globbing, as explained next.

Example 18.64.

(The Script)
    #!/bin/perl
1   @myfiles=<*.[1-5]>;
2   print "@myfiles\n";
3   foreach $file ( <p??l[1-5]*>){
4      print "$file\n" if -T $file;
    }
(Output)
2   exer.3 exer.4 exer.5 fileter.1 format.1 format.2 format.3 perl.4
perl.4.1
4   perl1
    perl2
    perl3
    perl4
    perl4.1
    perl5

Explanation

  1. In an array context, after the globbing is performed, a list of all the matched files is returned and returned to the array @myfiles. The list consists of any files that start with zero or more of any character, followed by a period, and ending with a number between 1 and 5.

  2. The list of matched files is printed.

  3. The foreach loop is entered. Each time through the loop, the scalar $file is set to the next file that is successfully globbed; that is, any file starting with a p, followed by any two characters, followed by an l, followed by a number between 1 and 5, and ending in zero or more of any character.

  4. If the file is a text file (-T), its name is printed.

The glob Function

The glob function does the same thing as the <*> operator. It expands the filename metacharacters just as the shell does and returns the expanded filenames.

Example 18.65.

(Command Line)
1   $ perl -e 'while(glob("p???[1-5]")) {print "$_\n";}'
    perl1
    perl2
    perl3
    perl4
    perl5

(In Script)
2   while ( glob("p???[1-5]")){
3       print "$_\n";
    }
(Output)
3   perl1
    perl2
    perl3
    perl4
    perl5

Explanation

  1. At the command line, the glob function will "glob" onto any files in the current working directory whose name begins with a p, followed by any three characters (???), followed by any number between 1 and 5 ([1–5]). Each filename that matches the expression is assigned to $_ and then printed.

  2. This time, glob is being used in a script. The behavior is exactly the same as in the first example.

  3. The expanded filenames are printed.

Previous Page Next Page