You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@httpd.apache.org by Andrus <ee...@online.ee> on 2003/07/10 17:42:25 UTC

[users@httpd] Premature end of script headers using CGI appl in Linux

 I have a CGI app which interfaces with my application. I use Apache 2
 In Windows it works OK.

 I re-compiled this CGI app using Windowsis Dev-C++ 4.9.8.0   using Linux
 modules.
 After that I got the following error from Apache:

  Premature end of script headers: eva.exe

 Any idea how to fix this ?

 My CGI app code is as follows:

#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winbase.h>
#include <time.h>
#include <direct.h>
#include <sys/timeb.h>

#include <fcntl.h>
#include <io.h>

#define TEMP_PREFIX_LENGTH 8  // Length of temporary file prefix excluding
null terminator
#define DATA_BUFFER_LENGTH 1000  // Length of data buffer.

#define MAX_FILE_ATTEMPTS  10  // Number of times to attempt creating temp
file.
#define ACK_RETRY_MILLISECONDS 250  // Number of milliseconds for each retry
attempt to read ACK file.
#define ACK_TIMEOUT_SECONDS     60  // Number of seconds until attempts to
read ACK file time out.

#define SERVER_INACCESSIBLE_TITLE_LOC "Server Inaccessible"
#define SERVER_INACCESSIBLE_TEXT_LOC "Communication with the server is not
possible at this time."
#define SERVER_TIMEOUT_TITLE_LOC "Server Timeout"
#define SERVER_TIMEOUT_TEXT_LOC  "The server timed out. It is probably too
busy to fulfill your request."
#define SERVER_NODATA_TITLE_LOC "Server Error"
#define SERVER_NODATA_TEXT_LOC "A server error occurred.  No return data was
sent."

void errorform( char *errorstring, char *errortitle );

void main( int argc, char *argv[] )
{

 char tmpPrefix[TEMP_PREFIX_LENGTH+1];
 char tmpFolder[] = "\\temp";
 char tmpName[_MAX_PATH];

 char *t1   = NULL;
 char *tempbuffer = NULL;

 char datFileName[_MAX_PATH];
 char ackFileName[_MAX_PATH];
 char atnFileName[_MAX_PATH];

 FILE *datFile    = NULL;
 FILE *atnFile    = NULL;
 FILE *tempFile   = NULL;
 struct _timeb timebuffer;


 char buffer[DATA_BUFFER_LENGTH];
 int cont_len, bytesread, fileattempts;
 time_t begintout, chktout;
 char **envptr;
 fpos_t pos;

 // Turn stdin buffering off
 setvbuf( stdin, NULL, _IONBF, 0 );

setmode( fileno(stdout), O_BINARY );

 // Create server.app compatible temporary folder.
 // Note:  Server.app is looking for files in <current drive>:\temp,
 // not in the actual system temporary folder.
 _mkdir( tmpFolder );

 // Seed random number generator and zero fileattempts counter.
 _ftime( &timebuffer );
 srand( ((timebuffer.time & 0xFF)<<10) | timebuffer.millitm );
 fileattempts = 0;

 for (;;)
 {

  fileattempts++;

  // If we've tried MAX_FILE_ATTEMPTS times, give error message.
  if ( fileattempts > MAX_FILE_ATTEMPTS )
  {
   errorform( SERVER_INACCESSIBLE_TEXT_LOC, SERVER_INACCESSIBLE_TITLE_LOC );
   goto CleanupAndExit;
  }

  // Create random file name. Format is "VF" plus unique 4 digit hex number
  // representing the processid, plus 2 digit random number (in case
multiple
  // machines are running the CGI scripts).
  sprintf( tmpPrefix, "VF%04X%02X", (DWORD) GetCurrentProcessId(), rand() &
0xFF);

  // Build temporary file name.
  sprintf( tmpName, "%s\\%s", tmpFolder, tmpPrefix );

  // Create the names for the three files.
  sprintf( datFileName, "%s.dat", tmpName );
  sprintf( ackFileName, "%s.ack", tmpName );
  sprintf( atnFileName, "%s.atn", tmpName );

  // Create data file.
  datFile = fopen( datFileName, "a" );

  // Make sure data file didn't already exist.
  if ( NULL != datFile )
  {
   // Seek to the end of the file.
   fseek( datFile, 0, SEEK_END );
   if( 0 == fgetpos( datFile, &pos ) )
   {
    // We know fgetpos was successful, now check position.
    // If pos is zero, we know we have a new file and can break out of loop.
    if ( 0 == pos ) break;
   }
   fclose( datFile );
  }

 }

 // We could check REQUEST_METHOD here, but what would be the point?
 // If CONTENT_LENGTH is NULL, we won't read the stdin, otherwise we will.
 // This is entirely for POST method requests.
 t1 = getenv( "CONTENT_LENGTH" );
 if ( NULL != t1 )
 {
  cont_len = atoi( t1 );

  tempbuffer = (char *) malloc( sizeof(char) * cont_len );
  if ( NULL == tempbuffer )
  {
   goto CleanupAndExit;
  }

  bytesread = fread( tempbuffer, sizeof(char), cont_len, stdin );
  if ( 0 != bytesread )
   fwrite( tempbuffer, sizeof(char), bytesread, datFile );

  free( tempbuffer );
 }

 // This part reads all of the environment variables and sends
 // them along in the DAT file as well. All ampersand delimited.
 envptr = environ;
 while ( NULL != *envptr )
 {
  fputs( "&", datFile );
  fputs( *envptr, datFile );
  envptr++;
 }
 fclose( datFile );

 // Create ATN File
 atnFile = fopen( atnFileName,"w" );
 if ( NULL == atnFile )
 {
  errorform( SERVER_INACCESSIBLE_TEXT_LOC , SERVER_INACCESSIBLE_TITLE_LOC );
  goto CleanupAndExit;
 }

 fclose( atnFile );

 _flushall();

 // Wait for Server to ACK
 time( &begintout );
 do
 {
  tempFile = fopen( ackFileName, "r" );
  if ( NULL != tempFile ) break; // Break before sleep if successful.
  time( &chktout );
  Sleep( ACK_RETRY_MILLISECONDS );
 //if _access() can't find the file, then the query is currently being
processed.
 //Keep looping for another ACK_TIMEOUT_SECONDS.
 } while ( ( NULL == tempFile ) && (( difftime( chktout, begintout ) <
ACK_TIMEOUT_SECONDS )
  || ((_access(atnFileName,0) == -1) && ( difftime( chktout, begintout ) <
(2*ACK_TIMEOUT_SECONDS) ))));

 if ( NULL != tempFile )
 {
  fclose( tempFile );
 }
 else
 {
  errorform( SERVER_TIMEOUT_TEXT_LOC , SERVER_TIMEOUT_TITLE_LOC);
  goto CleanupAndExit;
 }

 // Send the Data file to stdout.
 datFile = fopen( datFileName, "rb" );
 if ( NULL == datFile )
 {
  errorform( SERVER_NODATA_TEXT_LOC , SERVER_NODATA_TITLE_LOC);
  goto CleanupAndExit;
 }
 else
 {
  // Return results to web server.
  while ( !feof( datFile ) )
  {
// prb: kas stdout on binaarne
int len;
len = fread( buffer, 1, DATA_BUFFER_LENGTH, datFile );
if (len==0) break;
fwrite( buffer, 1, len, stdout );
  }
  fclose( datFile );
 }

CleanupAndExit:

 // Close all file handles.
 _fcloseall();

 // Remove temporary files.
 remove( ackFileName );
 remove( datFileName );
 remove( atnFileName );

 return;

}

void errorform( char *errorstring, char *errortitle )
{
 printf( "Content-Type: text/html\n\n" );
 printf( "<head><title>%s</title></head>\n", errortitle );
 printf( "<body>\n<h1>%s</h1>\n", errortitle );
 printf( "%s<hr>\n</body>", errorstring );
}


---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] Premature end of script headers using CGI appl in Linux

Posted by Robert Andersson <ro...@profundis.nu>.
Andrus wrote:
>    goto CleanupAndExit;

Oh, dear ;-)

> // Return results to web server.
> while ( !feof( datFile ) )
> {
>     // prb: kas stdout on binaarne
>     int len;
>     len = fread( buffer, 1, DATA_BUFFER_LENGTH, datFile );
>     if (len==0) break;
>     fwrite( buffer, 1, len, stdout );

I cannot see that the Content-Type header is written before this statement
is executed.

> void errorform( char *errorstring, char *errortitle )
> {
>     printf( "Content-Type: text/html\n\n" );

At least on Windows, I have noted, <CRLF> must be written "\r\n", like:

printf("Content-Type: text/html\r\n\r\n");


Regards,
Robert Andersson




---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] Premature end of script headers using CGI appl in Linux

Posted by Lee Fellows <lf...@4lane.com>.
On Thu, 2003-07-10 at 11:42, Andrus wrote:
>  I have a CGI app which interfaces with my application. I use Apache 2
>  In Windows it works OK.
> 
>  I re-compiled this CGI app using Windowsis Dev-C++ 4.9.8.0   using Linux
>  modules.
>  After that I got the following error from Apache:
> 
>   Premature end of script headers: eva.exe
> 
>  Any idea how to fix this ?

  Aside from your errorform routine, it does not appear to send the needed
  Content headers prior to dumping the file contents.



---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org