352 Chapter 16 Interacting with the File System and the Server Using Program Execution Functions We’ll move away from the file system functions now, and look at the functions that are available for running commands on the server. This is useful when you want to provide a Web-based front end to an existing com- mand line-based system. For example, we have used these commands to set up a front end for the mailing list manager ezmlm.We will use these again when we come to the case studies later in this book. There are four main techniques you can use to execute a command on the Web serv- er.They are all pretty similar, but there are some minor differences. 1. exec() The exec() function has the following prototype: string exec (string command [, array result [, int return_value]]) You pass in the command that you would like executed, for example, exec("ls -la"); The exec() function has no direct output. It returns the last line of the result of the command. If you pass in a variable as result,you will get back an array of strings repre- senting each line of the output. If you pass in a variable as return_value,you will get the return code. 2. passthru() The passthru() function has the following prototype: void passthru (string command [, int return_value]) The passthru() function directly echoes its output through to the browser. (This is useful if the output is binary, for example, some kind of image data.) It returns nothing. The parameters work the same way as exec()’s parameters do. 3. system() The system() function has the following prototype: string system (string command [, int return_value]) The function echoes the output of the command to the browser. It tries to flush the output after each line (assuming you are running PHP as a server module), which distinguishes it from passthru(). It returns the last line of the output (upon success) or false (upon failure). The parameters work the same way as in the other functions. 21 525x ch16 1/24/03 3:41 PM Page 352 353 Using Program Execution Functions 4. Backticks We mentioned these briefly in Chapter 1,“PHP Crash Course.”These are actually an execution operator. They have no direct output.The result of executing the command is returned as a string, which can then be echoed or whatever you like. If you have more complicated needs, you can also use popen(), proc_open(), and proc_close(), which are used to fork external processes and pipe data to and from them. The last two of these functions were added at PHP 4.3. The script shown in Listing 16.5 illustrates how to use each of the four techniques in an equivalent fashion. Listing 16.5 progex.php—File Status Functions and Their Results <?php chdir('/uploads/'); ///// exec version echo '<pre>'; // unix exec('ls -la', $result); // windows // exec('dir', $result); foreach ($result as $line) echo "$line\n"; echo '</pre>'; echo '<br /><hr /><br />'; ///// passthru version echo '<pre>'; // unix passthru('ls -la'); // windows // passthru('dir'); echo '</pre>'; echo '<br /><hr /><br />'; ///// system version echo '<pre>'; 21 525x ch16 1/24/03 3:41 PM Page 353 354 Chapter 16 Interacting with the File System and the Server // unix $result = system('ls -la'); // windows // $result = system('dir'); echo '</pre>'; echo '<br /><hr /><br />'; /////backticks version echo '<pre>'; // unix $result = `ls -al`; // windows // $result = `dir`; echo $result; echo '</pre>'; ?> We could have used one of these approaches as an alternative to the directory-browsing script we wrote earlier. Note that one of the side effects of using external functions is amply demonstrated by this code—your code is no longer portable.We have used Unix commands here and the code will clearly not run on Windows. If you plan to include user-submitted data as part of the command you’re going to execute, you should always run it through the escapeshellcmd() function first.This stops users from maliciously (or otherwise) executing commands on your system.You can call it like this, for example, system(escapeshellcmd($command)); You should also use the escapeshellarg() function to escape any arguments you plan to pass to your shell command. Interacting with the Environment: getenv() and putenv() Before we leave this section, we’ll look at how you can use environment variables from within PHP.There are two functions for this purpose: getenv(), which enables you to retrieve environment variables, and putenv(), which enables you to set environment variables. Note that the environment we are talking about here is the environment in which PHP runs on the server. Listing 16.5 Continued 21 525x ch16 1/24/03 3:41 PM Page 354 355 Next You can get a list of all PHP’s environment variables by running phpinfo(). Some are more useful than others, for example, getenv("HTTP_REFERER"); will return the URL of the page from which the user came to the current page. You can also set environment variables as required with putenv(), for example, $home = "/home/nobody"; putenv (" HOME=$home "); If you are a system administrator and would like to limit which environment variables programmers can set, you can use the safe_mode_allowed_env_vars directive in php.ini. When PHP runs in safe mode, users will only be able to set environment vari- ables whose prefixes are listed in this directive. If you would like more information about what some of the environment variables represent, you can look at the CGI specification: http://hoohoo.ncsa.uiuc.edu/cgi/env.html Further Reading Most of the file system functions in PHP map to underlying operating system func- tions—try reading the man pages if you’re using UNIX for more information. Next In Chapter 17,“Using Network and Protocol Functions,” we’ll use PHP’s network and protocol functions to interact with systems other than our own Web server.This again expands the horizons of what we can do with our scripts. 21 525x ch16 1/24/03 3:41 PM Page 355 21 525x ch16 1/24/03 3:41 PM Page 356 . server. This is useful when you want to provide a Web- based front end to an existing com- mand line-based system. For example, we have used these commands to set up a front end for the mailing list. execute a command on the Web serv- er.They are all pretty similar, but there are some minor differences. 1. exec() The exec() function has the following prototype: string exec (string command [, array. use popen(), proc_open(), and proc_close(), which are used to fork external processes and pipe data to and from them. The last two of these functions were added at PHP 4.3. The script shown in