title: How to call php-cgi from c++
body: <p>So I'm writing a web server (I know, like the world needs another one!) And I want to call php through CGI. I've got a nice working CGI1.1 implementation good enough to run perl cgi scripts for example.</p>
  
  <p>Now I want to run php. But when my cgi module calls the php program it returns a 404.</p>
  
  <p>How do I get this working?</p>
  
  <p>The details:</p>
  
  <p>I'm running on ubuntu with php5. In my web server, I pass cgi requests to a handler that will find the program and call it with the sc ript as an argument. So here is the code that spawns the cgi process:</p>
  
  <pre><code>chdir( dir );
  execve( argv[0], argv.data(), (char* const*) req.posixEnv() );
  </code></pre>
  
  <p>The command I'm running is equivalent to:</p>
  
  <pre><code>/usr/bin/php5-cgi /home/rafael/webserver/data/cgi-bin/test.php
  </code></pre>
  
  <p>This means I've set "dir" to:</p>
  
  <pre><code>/home/rafael/webserver/data/cgi-bin
  </code></pre>
  
  <p>And the cgi process should run in that directory. Argv[0] is "/usr/bin/php5-cgi", argv.data() returns a null terminated array with the following elements:</p>
  
  <pre><code>/usr/bin/php5-cgi
  /home/rafael/webserver/data/cgi-bin/test.php
  NULL
  </code></pre>
  
  <p>The process environment contains the CGI environment that includes a block of the usual CGI environment variables.</p>
  
  <p>When I run the above command from a shell, that is by literally typing it into a shell, the script runs fine and php generates the test page. When I call it from CGI it returns:</p>
  
  <pre><code>Status: 404 Not Found
  X-Powered-By: PHP/5.3.10-1ubuntu3.2
  Content-type: text/html
  
  No input file specified.
  </code></pre>
  
  <p>Now I know more or less what is happening. PHP is detecting if it is running in CLI or CGI mode, and searching for the script to run differently in each mode. In CGI mode it is probably using CGI environment variables like SCRIPT_FILENAME and DOCUMENT_ROOT to resolve the script name. I've tried a whole bunch of things - different settings for these variables. But none of it works.</p>
  
  <p>What I do know: The whole spawning of PHP, and reading output works. For example if I remove  certain CGI variables such that it thinks it is running in CLI mode it works great - generates the page and everything.</p>
  
  <p>What I need to know is:</p>
  
  <ol>
  <li>what is the right way to set up the CGI environment variables for the php-cgi to find my script. </li>
  <li>what is the right way to call a php script from exec. I'm using full paths for everything as an effort to debug this. I'd prefer to use relative paths.</li>
  </ol>
  
  <p>All the documentation I can find is about configuring php for cgi on particular web servers. I need to know this from the perspective of someone writing a server.</p>
  
  <p>@EDIT: I have a simpler example that eliminates c++. I'm pretty sure that part is working correctly anyway. Say I make a script that calls php-cgi, and I try to emulate the cgi calling conventions in a shell.</p>
  
  <p>This works:</p>
  
  <pre><code>#export GATEWAY_INTERFACE="CGI/1.1"                                                                                             
  export REDIRECT_STATUS=200
  export SERVER_PROTOCOL="HTTP/1.1"
  export DOCUMENT_ROOT="/home/rafael/web"
  #export SCRIPT_FILENAME="cgi-bin/test.php"                                                                                      
  export SCRIPT_NAME="cgi-bin/test.php"
  
  /usr/bin/php5-cgi test.php
  </code></pre>
  
  <p>But this doesn't:</p>
  
  <pre><code>export GATEWAY_INTERFACE="CGI/1.1"                                                                                             
  export REDIRECT_STATUS=200
  export SERVER_PROTOCOL="HTTP/1.1"
  export DOCUMENT_ROOT="/home/rafael/web"
  #export SCRIPT_FILENAME="cgi-bin/test.php"                                                                                      
  export SCRIPT_NAME="cgi-bin/test.php"
  
  /usr/bin/php5-cgi test.php
  </code></pre>
  
  <p>I think probably some combination of DOCUMENT_ROOT, SCRIPT_FILENAME and SCRIPT_NAME should work.</p>