Ok, I've solved this now. It took a few steps. The first one was generating a file that contained a request (inspired by chromatic's suggestion). The basics of that are given above. Additionally, I needed to trim off the headers (so the first line looks like this: --xYzZY), because that's the way that the Perl script expects to receive it.
Next, I actually sent the request to a Perl script, and then dumped out %ENV to capture that. This gives me the correct content length, and other needed environment variables
Finally, I created the test script, which is fooled into thinking that is is normal file upload, because all the environmental variables are set, and the data is coming in on STDIN. I tried tying the filehandle directly instead of duplicating it with STDIN, but that didn't work.
So with my working input file, here's a snippet from the test script:
%ENV = (
%ENV,
'SCRIPT_NAME' => '/test.cgi',
'SERVER_NAME' => 'perl.org',
'HTTP_CONNECTION' => 'TE, close',
'REQUEST_METHOD' => 'POST',
'SCRIPT_URI' => 'http://www.perl.org/test.cgi',
'CONTENT_LENGTH' => '2986',
'SCRIPT_FILENAME' => '/home/usr/test.cgi',
'SERVER_SOFTWARE' => 'Apache/1.3.27 (Unix) ',
'HTTP_TE' => 'deflate,gzip;q=0.3',
'QUERY_STRING' => '',
'REMOTE_PORT' => '1855',
'HTTP_USER_AGENT' => 'libwww-perl/5.69',
'SERVER_PORT' => '80',
'REMOTE_ADDR' => '127.0.0.1',
'CONTENT_TYPE' => 'multipart/form-data; boundary=xYzZY',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'PATH' => '/usr/local/bin:/usr/bin:/bin',
'REQUEST_URI' => '/test.cgi',
'GATEWAY_INTERFACE' => 'CGI/1.1',
'SCRIPT_URL' => '/test.cgi',
'SERVER_ADDR' => '127.0.0.1',
'DOCUMENT_ROOT' => '/home/develop',
'HTTP_HOST' => 'www.perl.org'
);
use CGI;
open(IN,'<t/post_text.txt');
*STDIN = *IN;
$q = new CGI;
-mark |