For any given weird, seemingly pointless action, you will be able to find at least 3 good, interesting reasons for wanting to take that action (provided you look around hard enough). In my case, the action was calling a cgi script from php, and the reason was to implement a good logging system. I run a bugzilla installation here, and I didn’t want to go editing every page to get a logger. I also didn’t want to use Apache’s own loggers, since a MySQL database is much easier to handle than a super-sized file.

My solution was to create an index.php file and modify the htaccess so that every request to the bugzilla installation went through index.php. Then, I could have index.php log the event, and call the appropriate cgi script.

There are various ways to almost run a cgi script from within a php script. All that I know of are based on the fact that a cgi script is really nothing more than an executable whose output Apache delivers to a client on the other end of the connection – hence the ’shebang’ line on top:

#!/usr/bin/perl -wT

If the cgi happens to be an executable, this is even more obvious.

Therefore, to ‘call the cgi script’, we can just run it as a program:

  1. system("/usr/bin/perl -T index.cgi");
  2. //or, if we want
  3. system("./index.cgi");

While these look really neat, you’ll discover that the header information is sent as raw text, and that it appears at the top of the webpage that gets displayed. That’s not just a nuisance – it also means that the browser is not receiving its header information. At best, the browser will be annoyed. At worst, the browser will be IE 8, and it will crash. Most often, you’ll just discover that nothing is displaying right, for mysterious reasons.

We could write a complicated 20-line php function to pass down the headers, but the clean solution is to use an Apache-specific php function: virtual(). This function takes as an argument the filename of a cgi script, and calls that script as if it had been called directly from Apache’s internals. Which is, to put it lightly, exactly what we wanted.

This function only works when php is operating as an Apache module – but presumably, the problem of the headers (mentioned above) is trivial if php is operating as a cgi script. That would also be preferable if you are not in Apache, since the virtual function is Apache-specific.

Related posts: