Ejemplo n.º 1
0
Archivo: system.c Proyecto: phs75/gap
/****************************************************************************
**
*F  SySetInitialGapRootPaths( <string> )  . . . . .  set the root directories
**
**  Set up GAP's initial root paths, based on the location of the
**  GAP executable.
*/
static void SySetInitialGapRootPaths(void)
{
    if (GAPExecLocation[0] != 0) {
        // GAPExecLocation might be a subdirectory of GAP root,
        // so we will go and search for the true GAP root.
        // We try stepping back up to two levels.
        char pathbuf[GAP_PATH_MAX];
        char initgbuf[GAP_PATH_MAX];
        strxcpy(pathbuf, GAPExecLocation, sizeof(pathbuf));
        for (Int i = 0; i < 3; ++i) {
            strxcpy(initgbuf, pathbuf, sizeof(initgbuf));
            strxcat(initgbuf, "lib/init.g", sizeof(initgbuf));

            if (SyIsReadableFile(initgbuf) == 0) {
                SySetGapRootPath(pathbuf);
                // escape from loop
                return;
            }
            // try up a directory level
            strxcat(pathbuf, "../", sizeof(pathbuf));
        }
    }

    // Set GAP root path to current directory, if we have no other
    // idea, and for backwards compatibility.
    // Note that GAPExecLocation must always end with a slash.
    SySetGapRootPath("./");
}
Ejemplo n.º 2
0
// fill in file name in buffer pointed by filename
FRESULT philes_nextfile(char *filename, uint8_t terminate) {
	while ((f_readdir(&dir, &finfo) == FR_OK) && finfo.fname[0]) {
		if (finfo.fattrib & AM_DIR) {
			// nowai
		} else {
			if (endsWith(finfo.fname, ".FDD")) {
				if (filename != 0) {
					if (terminate) {
						strncpy(filename, finfo.fname, 12);
					} else {
						strxcpy(filename, finfo.fname);
					}
				}
				return 0;
			}
		}
	}
	
	return FR_NO_FILE;
}
Ejemplo n.º 3
0
static UInt GetMasterPty ( int *pty, Char *nametty, Char *namepty )
{
#if HAVE_POSIX_OPENPT && HAVE_PTSNAME
    /* Attempt to use POSIX 98 pseudo ttys. Opening a master tty is done
       via posix_openpt, which is available on virtually every current
       UNIX system; indeed, according to gnulib, it is available on at
       least the following systems:
         - glibc >= 2.2.1 (released January 2001; but is a stub on GNU/Hurd),
         - Mac OS X >= 10.4 (released April 2005),
         - FreeBSD >= 5.1 (released June 2003),
         - NetBSD >= 3.0 (released December 2005),
         - AIX >= 5.2 (released October 2002),
         - HP-UX >= 11.31 (released February 2007),
         - Solaris >= 10 (released January 2005),
         - Cygwin >= 1.7 (released December 2009).
       Systems lacking posix_openpt (in addition to older versions of
       the systems listed above) include:
         - OpenBSD
         - Minix 3.1.8
         - IRIX 6.5
         - OSF/1 5.1
         - mingw
         - MSVC 9
         - Interix 3.5
         - BeOS
       */
    *pty = posix_openpt( O_RDWR | O_NOCTTY );
    if (*pty > 0) {
        if (grantpt(*pty) || unlockpt(*pty)) {
            close(*pty);
            return 1;
        }
        strxcpy(nametty, ptsname(*pty), 32);
        return 0;
    }
    return 1;

#elif HAVE_GETPT && HAVE_PTSNAME_R
    /* Attempt to use glibc specific APIs, for compatibility with older
       glibc versions (before 2.2.1, release January 2001). */
    *pty = getpt();
    if (*pty > 0) {
        if (grantpt(*pty) || unlockpt(*pty)) {
            close(*pty);
            return 1;
        }
        ptsname_r(*pty, nametty, 32); 
        return 0;
    }
    return 1;

#elif HAVE_PTSNAME
    /* Attempt to use Sys V pseudo ttys on systems that don't have posix_openpt,
       getpt or openpty, but do have ptsname.
       Platforms *missing* ptsname include:
       Mac OS X 10.3, OpenBSD 3.8, Minix 3.1.8, mingw, MSVC 9, BeOS. */
    *pty = open( "/dev/ptmx", O_RDWR );
    if ( *pty < 0 )
        return 1;
    strxcpy(nametty, ptsname(*pty), 32);
    return 0;

#elif HAVE_GETPSEUDOTTY
    /* TODO: From which system(s) does getpseudotty originate? */
    *pty = getpseudotty( nametty, namepty );
    return *pty < 0 ? 1 : 0;

#elif HAVE__GETPTY
    /* Available on SGI IRIX >= 4.0 (released September 1991).
       See also http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?cmd=getdoc&coll=0530&db=man&fname=7%20pty */
    char  * line;
    line = _getpty(pty, O_RDWR|O_NDELAY, 0600, 0) ;
    if (0 == line)
        return 1;
    strcpy( nametty, line );
    return 0;

#else
    /* fallback to old-style BSD pseudoterminals, doing a brute force
       search over all pty device files. */
    int devindex;
    int letter;
    int ttylen, ptylen;

    ttylen = strlen(nametty);
    ptylen = strlen(namepty);

    for ( letter = 0; SYS_PTYCHAR1[letter]; ++letter ) {
        nametty[ttylen-2] = SYS_PTYCHAR1[letter];
        namepty[ptylen-2] = SYS_PTYCHAR1[letter];

        for ( devindex = 0; SYS_PTYCHAR2[devindex]; ++devindex ) {
            nametty[ttylen-1] = SYS_PTYCHAR2[devindex];
            namepty[ptylen-1] = SYS_PTYCHAR2[devindex];
                    
            *pty = open( namepty, O_RDWR );
            if ( *pty >= 0 ) {
                int slave = open( nametty, O_RDWR );
                if ( slave >= 0 ) {
                    close(slave);
                    return 0;
                }
                close(*pty);
            } 
        }
    }
    return 1;
#endif
}
Ejemplo n.º 4
0
Archivo: system.c Proyecto: phs75/gap
static void SySetGapRootPath( const Char * string )
{
    const Char *          p;
    Char *          q;
    Int             i;
    Int             n;

    /* set string to a default value if unset                              */
    if ( string == 0 || *string == 0 ) {
        string = "./";
    }
 
    /* 
    ** check if we append, prepend or overwrite. 
    */ 
    if( string[0] == ';' ) {
        /* Count the number of root directories already present.           */
         n = 0; while( SyGapRootPaths[n][0] != '\0' ) n++;

         /* Skip leading semicolon.                                        */
         string++;

    }
    else if( string[ strlen(string) - 1 ] == ';' ) {
        /* Count the number of directories in 'string'.                    */
        n = 0; p = string; while( *p ) if( *p++ == ';' ) n++;

        /* Find last root path.                                            */
        for( i = 0; i < MAX_GAP_DIRS; i++ ) 
            if( SyGapRootPaths[i][0] == '\0' ) break;
        i--;

#ifdef HPCGAP
        n *= 2; // for each root <ROOT> we also add <ROOT/hpcgap> as a root
#endif

        /* Move existing root paths to the back                            */
        if( i + n >= MAX_GAP_DIRS ) return;
        while( i >= 0 ) {
            memcpy( SyGapRootPaths[i+n], SyGapRootPaths[i], sizeof(SyGapRootPaths[i+n]) );
            i--;
        }

        n = 0;

    }
    else {
        /* Make sure to wipe out all possibly existing root paths          */
        for( i = 0; i < MAX_GAP_DIRS; i++ ) SyGapRootPaths[i][0] = '\0';
        n = 0;
    }

    /* unpack the argument                                                 */
    p = string;
    while ( *p ) {
        if( n >= MAX_GAP_DIRS ) return;

        q = SyGapRootPaths[n];
        while ( *p && *p != ';' ) {
            *q = *p++;

#ifdef SYS_IS_CYGWIN32
            /* fix up for DOS */
            if (*q == '\\')
              *q = '/';
#endif
            
            q++;
        }
        if ( q == SyGapRootPaths[n] ) {
            strxcpy( SyGapRootPaths[n], "./", sizeof(SyGapRootPaths[n]) );
        }
        else if ( q[-1] != '/' ) {
            *q++ = '/';
            *q   = '\0';
        }
        else {
            *q   = '\0';
        }
        if ( *p ) {
            p++;
        }
        n++;
#ifdef HPCGAP
        // or each root <ROOT> we also add <ROOT/hpcgap> as a root (and first)
        if( n < MAX_GAP_DIRS ) {
            strlcpy( SyGapRootPaths[n], SyGapRootPaths[n-1], sizeof(SyGapRootPaths[n]) );
        }
        strxcat( SyGapRootPaths[n-1], "hpcgap/", sizeof(SyGapRootPaths[n-1]) );
        n++;
#endif
    }
}
Ejemplo n.º 5
0
Archivo: system.c Proyecto: phs75/gap
void InitSystem (
    Int                 argc,
    Char *              argv [] )
{
    Char *              *ptrlist;
    UInt                i;             /* loop variable                   */
    Int res;                       /* return from option processing function */

    /* Initialize global and static variables */
    SyCTRD = 1;             
    SyCompilePlease = 0;
    SyDebugLoading = 0;
    SyLineEdit = 1;
#ifdef HPCGAP
    SyUseReadline = 0;
#else
    SyUseReadline = 1;
#endif
    SyMsgsFlagBags = 0;
    SyNrCols = 0;
    SyNrColsLocked = 0;
    SyNrRows = 0;
    SyNrRowsLocked = 0;
    SyQuiet = 0;
    SyInitializing = 0;
#ifdef SYS_IS_64_BIT
    SyStorMin = 128 * 1024L;
    SyStorMax = 2048*1024L;          /* This is in kB! */
    SyAllocPool = 4096L*1024*1024;   /* Note this is in bytes! */
#else
    SyStorMin = 64 * 1024L;
    SyStorMax = 1024*1024L;          /* This is in kB! */
#ifdef SYS_IS_CYGWIN32
    SyAllocPool = 0;                 /* works better on cygwin */
#else
    SyAllocPool = 1536L*1024*1024;   /* Note this is in bytes! */
#endif
#endif
    SyStorOverrun = 0;
    SyStorKill = 0;
    SyUseModule = 1;
    SyWindow = 0;

    for (i = 0; i < 2; i++) {
      UInt j;
      for (j = 0; j < 7; j++) {
        SyGasmanNumbers[i][j] = 0;
      }
    }

    preAllocAmount = 4*1024*1024;

    InitSysFiles();

#ifdef HAVE_LIBREADLINE
    rl_initialize ();
#endif
    
    SyInstallAnswerIntr();

#if defined(SYS_DEFAULT_PATHS)
    SySetGapRootPath( SYS_DEFAULT_PATHS );
#else
    SySetInitialGapRootPaths();
#endif

    /* save the original command line for export to GAP */
    SyOriginalArgc = argc;
    SyOriginalArgv = argv;

    /* scan the command line for options that we have to process in the kernel */
    /* we just scan the whole command line looking for the keys for the options we recognise */
    /* anything else will presumably be dealt with in the library */
    while ( argc > 1 )
      {
        if (argv[1][0] == '-' ) {

          if ( strlen(argv[1]) != 2 && argv[1][1] != '-') {
            FPUTS_TO_STDERR("gap: sorry, options must not be grouped '");
            FPUTS_TO_STDERR(argv[1]);  FPUTS_TO_STDERR("'.\n");
            goto usage;
          }


          for (i = 0;  options[i].shortkey != argv[1][1] &&
                       (argv[1][1] != '-' || argv[1][2] == 0 || strcmp(options[i].longkey, argv[1] + 2)) &&
                       (options[i].shortkey != 0 || options[i].longkey[0] != 0); i++)
            ;

        


          if (argc < 2 + options[i].minargs)
            {
              Char buf[2];
              FPUTS_TO_STDERR("gap: option "); FPUTS_TO_STDERR(argv[1]);
              FPUTS_TO_STDERR(" requires at least ");
              buf[0] = options[i].minargs + '0';
              buf[1] = '\0';
              FPUTS_TO_STDERR(buf); FPUTS_TO_STDERR(" arguments\n");
              goto usage;
            }
          if (options[i].handler) {
            res = (*options[i].handler)(argv+2, options[i].otherArg);
            
            switch (res)
              {
              case -1: goto usage;
                /*            case -2: goto fullusage; */
              default: ;     /* fall through and continue */
              }
          }
          else
            res = options[i].minargs;
          /*    recordOption(argv[1][1], res,  argv+2); */
          argv += 1 + res;
          argc -= 1 + res;
          
        }
        else {
          argv++;
          argc--;
        }
          
      }
    /* adjust SyUseReadline if no readline support available or for XGAP  */
#if !defined(HAVE_LIBREADLINE)
    SyUseReadline = 0;
#endif
    if (SyWindow) SyUseReadline = 0;

    /* now that the user has had a chance to give -x and -y,
       we determine the size of the screen ourselves */
    getwindowsize();

    /* fix max if it is lower than min                                     */
    if ( SyStorMax != 0 && SyStorMax < SyStorMin ) {
        SyStorMax = SyStorMin;
    }

    /* fix pool size if larger than SyStorKill */
    if ( SyStorKill != 0 && SyAllocPool != 0 &&
                            SyAllocPool > 1024 * SyStorKill ) {
        SyAllocPool = SyStorKill * 1024;
    }
    /* fix pool size if it is given and lower than SyStorMax */
    if ( SyAllocPool != 0 && SyAllocPool < SyStorMax * 1024) {
        SyAllocPool = SyStorMax * 1024;
    }

    /* when running in package mode set ctrl-d and line editing            */
    if ( SyWindow ) {
      /*         SyLineEdit   = 1;
                 SyCTRD       = 1; */
        SyRedirectStderrToStdOut();
        syWinPut( 0, "@p", "1." );
    }
   

    if (SyAllocPool == 0) {
      /* premalloc stuff                                                     */
      /* allocate in small chunks, and write something to them
       * (the GNU clib uses mmap for large chunks and give it back to the
       * system after free'ing; also it seems that memory is only really 
       * allocated (pagewise) when it is first used)                     */
      ptrlist = (Char **)malloc((1+preAllocAmount/1000)*sizeof(Char*));
      for (i = 1; i*1000 < preAllocAmount; i++) {
        ptrlist[i-1] = (Char *)malloc( 1000 );
        if (ptrlist[i-1] != NULL) ptrlist[i-1][900] = 13;
      }
      for (i = 1; (i+1)*1000 < preAllocAmount; i++) 
        if (ptrlist[i-1] != NULL) free(ptrlist[i-1]);
      free(ptrlist);
       
     /* ptr = (Char *)malloc( preAllocAmount );
      ptr1 = (Char *)malloc(4);
      if ( ptr != 0 )  free( ptr ); */
    }

    /* should GAP load 'init/lib.g' on initialization */
    if ( SyCompilePlease || SyRestoring ) {
        SyLoadSystemInitFile = 0;
    }

    /* the compiler will *not* read in the .gaprc file                     
    if ( gaprc && ! ( SyCompilePlease || SyRestoring ) ) {
        sySetGapRCFile();
    }
    */

#ifdef HAVE_DOTGAPRC
    /* the users home directory                                            */
    if ( getenv("HOME") != 0 ) {
        strxcpy(DotGapPath, getenv("HOME"), sizeof(DotGapPath));
# if defined(SYS_IS_DARWIN) && SYS_IS_DARWIN
        /* On Darwin, add .gap to the sys roots, but leave */
        /* DotGapPath at $HOME/Library/Preferences/GAP     */
        strxcat(DotGapPath, "/.gap;", sizeof(DotGapPath));
        if (!IgnoreGapRC) {
          SySetGapRootPath(DotGapPath);
        }
		
        strxcpy(DotGapPath, getenv("HOME"), sizeof(DotGapPath));
        strxcat(DotGapPath, "/Library/Preferences/GAP;", sizeof(DotGapPath));
# elif defined(__CYGWIN__)
        strxcat(DotGapPath, "/_gap;", sizeof(DotGapPath));
# else
        strxcat(DotGapPath, "/.gap;", sizeof(DotGapPath));
# endif

        if (!IgnoreGapRC) {
          SySetGapRootPath(DotGapPath);
        }
        DotGapPath[strlen(DotGapPath)-1] = '\0';
        
        /* and in this case we can also expand paths which start
           with a tilde ~ */
        Char userhome[GAP_PATH_MAX];
        strxcpy(userhome, getenv("HOME"), sizeof(userhome));
        const UInt userhomelen = strlen(userhome);
        for (i = 0; i < MAX_GAP_DIRS && SyGapRootPaths[i][0]; i++) {
            const UInt pathlen = strlen(SyGapRootPaths[i]);
            if (SyGapRootPaths[i][0] == '~' &&
                userhomelen + pathlen < sizeof(SyGapRootPaths[i])) {
                SyMemmove(SyGapRootPaths[i] + userhomelen,
                        /* don't copy the ~ but the trailing '\0' */
                        SyGapRootPaths[i] + 1, pathlen);
                memcpy(SyGapRootPaths[i], userhome, userhomelen);
          }
        }
    }
#endif


    /* now we start                                                        */
    return;

    /* print a usage message                                               */
usage:
 FPUTS_TO_STDERR("usage: gap [OPTIONS] [FILES]\n");
 FPUTS_TO_STDERR("       run the Groups, Algorithms and Programming system, Version ");
 FPUTS_TO_STDERR(SyBuildVersion);
 FPUTS_TO_STDERR("\n");
 FPUTS_TO_STDERR("       use '-h' option to get help.\n");
 FPUTS_TO_STDERR("\n");
 SyExit( 1 );
}
Ejemplo n.º 6
0
FarString UnMimeHeader( LPCSTR header, int FarEncoding )
{
  char enc[ 256 ], tmp[ 256 ];
  FarString res;

  CBase64Decoder b64;
  CQuotedPrintableSubjectDecoder qp;

  LPCSTR ps = header, pe = ps, pb, pm;

  while ( ( pb = strstr( ps, "=?" ) ) != NULL )
  {
    if ( pb - ps > 0 )
      res += ToOEMString( FarString( ps, pb - ps ), FarEncoding );

    pb += 2;

    if ( ( pm = strchr( pb, '?' ) ) != NULL )
    {
      int dc = FarSF::LUpper( *++pm );
      if ( dc == 'B' || dc == 'Q' )
      {
        if ( ( pe = strstr( pm + 2, "?=" ) ) != NULL )
        {
          strxcpy( enc, pb, pm - pb );

          strxcpy( tmp, pm + 2, pe - pm - 1 );

          CMimeDecoder * d;
          if ( dc == 'B' )
            d = &b64;
          else
            d = &qp;

          dc = d->decode( (PBYTE)tmp, strlen( tmp ) );
          if ( dc > 0 )
            tmp[ dc ] = '\0';

          long d_enc = getCharacterTableNoDefault( enc );

          if ( d_enc == FCT__INVALID )
            d_enc = FarEncoding;

          res += ToOEMString( tmp, d_enc );

          pe += 2;
          pb = pe;

          while ( *pe && isspace( (unsigned char)*pe ) ) pe ++;

          if ( pe[ 0 ] == '=' && pe[ 1 ] == '?' )
            pb = pe;
        }
        else
          pb = pm;
      }
    }

    ps = pb;
  }

  if ( *ps != '\0' )
    res += ToOEMString( ps, FarEncoding );

  return res;
}
Ejemplo n.º 7
0
status_t handle_request( RequestPB *pb )
{
	HTTPResponse	response;
	pb->closeConnection = false;
	
	const char		*sPtr; // General purpose string pointer
	// Temporary buffers
	int32			fieldSize = 1024;
	char			fieldValue[1024];
	char			headBuffer[1024];
	int32 			contentLength = 0;
	
	// ****
	// Get PATH_INFO and SCRIPT_NAME from path; Setup absPath of CGI
	// ****
	char PATH_INFO[1024];
	char SCRIPT_NAME[256];
	
	// Get SCRIPT_NAME
	strxcpy( SCRIPT_NAME, pb->resourcePath->Path(), 255 );
	
	strxcpy( PATH_INFO, pb->brURI->path+strlen( pb->resourcePath->Path()+1 ), 1023 );
	
	
	// Make absolute CGI path from web-directory and requested path
	BPath		absPath( pb->webDirectory->Path(), pb->resourcePath->Path()+1 );
	
	// ****
	// Make sure CGI exists and Check Permission
	// ****
	
	if( pb->authenticate &&	!pb->realms->Authenticate( pb->request, &response, pb->brURI->path, absPath.Path(), S_IXOTH ) )
	{
		pb->Logprintf( "%ld Status-Line: %s\n", pb->sn, response.GetStatusLine() );
		return B_OK;
	}
	
	// ****
	// Setup meta-variables in new environment
	// ****
	char		params[2048];
	
	// Should we use the CGI script command line?
	// This should be done on a GET or HEAD where the URL query string
	// 		does not contain any unencoded '=' characters.
	if( *pb->brURI->query && 
		((pb->request->GetMethod() == METHOD_GET)||(pb->request->GetMethod() == METHOD_HEAD))&&
		!strchr( pb->brURI->query, '=' ) )
	{
		uri_unescape_str( params, pb->brURI->query, 2048 );
	}
	else
		uri_unescape_str( params, pb->brURI->params, 2048 );
	
	// Environment to be used by the CGI
	Environment 	env( pb->environ );
	
	// AUTH_TYPE
	if( pb->request->FindHeader( kHEAD_AUTHORIZATION, fieldValue, fieldSize ) )
	{
		sPtr = fieldValue;
		sPtr = get_next_token( headBuffer, sPtr, fieldSize );
		env.PutEnv( "AUTH_TYPE", headBuffer );
		if( strcasecmp( headBuffer, "Basic" ) == 0 )
		{
			// REMOTE_USER
			sPtr = get_next_token( headBuffer, sPtr, fieldSize );
			decode_base64( headBuffer, headBuffer, fieldSize );
			sPtr = get_next_token( fieldValue, headBuffer, fieldSize, ":" );
			env.PutEnv( "REMOTE_USER", fieldValue );
		}
	}
	
	// CONTENT_LENGTH
	if( pb->request->FindHeader( kHEAD_LENGTH, fieldValue, fieldSize ) )
		env.PutEnv( "CONTENT_LENGTH", fieldValue );
	
	// CONTENT_TYPE
	if( pb->request->FindHeader( kHEAD_TYPE, fieldValue, fieldSize ) )
		env.PutEnv( "CONTENT_TYPE", fieldValue );
	
	// GATEWAY_INTERFACE
	env.PutEnv( "GATEWAY_INTERFACE", "CGI/1.1" );
	// HTTP_*
	for( int i=0; (sPtr = pb->request->HeaderAt( i )); i++ )
	{
		sPtr = get_next_token( fieldValue, sPtr, fieldSize, ":" );
		sprintf( headBuffer, "HTTP_%s", http_to_cgi_header( fieldValue ) );
		sPtr = get_next_token( fieldValue, sPtr, fieldSize, ":" );
		env.PutEnv( headBuffer, fieldValue );
	}
	
	// PATH_INFO
	env.PutEnv( "PATH_INFO", PATH_INFO );
	
	// PATH_TRANSLATED
	if( *PATH_INFO )
	{
		BPath		pathTrans( pb->webDirectory->Path(), PATH_INFO+1 );
		
		if( pathTrans.Path() )
			env.PutEnv( "PATH_TRANSLATED", pathTrans.Path() );
	}
	
	// QUERY_STRING
	env.PutEnv( "QUERY_STRING", pb->brURI->query );
	
	// REMOTE_ADDR
	env.PutEnv( "REMOTE_ADDR", pb->request->GetRemoteHost() );
	
	// REMOTE_HOST
	// Ya, right... like were going to waste valuable time with a DNS lookup!
	env.PutEnv( "REMOTE_HOST", "" );
	
	// REMOTE_IDENT
	// Ha! Perform an Ident lookup... I don't think so.
	
	// REQUEST_METHOD
	env.PutEnv( "REQUEST_METHOD", http_find_method( pb->request->GetMethod() ) );
	
	// SCRIPT_NAME
	env.PutEnv( "SCRIPT_NAME", SCRIPT_NAME );
	
	// SERVER_NAME
	env.PutEnv( "SERVER_NAME", pb->brURI->host );
	
	// SERVER_PORT
	sprintf( fieldValue, "%u", pb->request->GetPort() );
	env.PutEnv( "SERVER_PORT", fieldValue );
	
	// SERVER_PROTOCOL
	env.PutEnv( "SERVER_PROTOCOL", pb->request->GetVersion() );
	
	// SERVER_SOFTWARE
	env.PutEnv( "SERVER_SOFTWARE", "RobinHood" );
	
	// PWD
	BPath		PWD( absPath );
	PWD.GetParent( &PWD );
	env.PutEnv( "PWD", PWD.Path() );
	
	// ****
	// Create pipes
	// ****
	
	pid_t	pid;
	int 	ipipe[2], opipe[2];
	
	if( pipe(ipipe) < 0 )
	{
		response.SetHTMLMessage( 500, "Pipe creation failed!" );
		pb->request->SendReply( &response );
		return B_OK;
	}
	if( pipe(opipe) < 0 ) 
	{
		close( ipipe[0] );
		close( ipipe[1] );
		response.SetHTMLMessage( 500, "Pipe creation failed!" );
		pb->request->SendReply( &response );
		return B_OK;
	}
	
	// ****
	// Setup args for execve()
	// ****
	
	// Setup command string; copy CGI path and append params
	char command[4096];
	sPtr = strxcpy( command, absPath.Path(), 4095 );
	
	// Disabled because of security risk
	/*
	if( *params && !strpbrk( params, ";&" ) )
	{
		sPtr = strxcpy( (char *)sPtr, " ", command+4095-sPtr );
		strxcpy( (char *)sPtr, params, command+4095-sPtr ); // Append params
	}*/
	
	char *args[4];
	args[0] = "/bin/sh";
	args[1] = "-c";
	args[2] = command;
	args[3] = NULL;
	
	pb->Logprintf( "%ld Exec: %s\n", pb->sn, command );
	
	// ****
	// Start sub-process using fork() dup2() and exec()
	// ****
	
	pid = fork();
	if( pid == (pid_t)0 ) // If we are the child process...
	{
		// Make this process the process group leader
		setpgid( 0, 0 );
		fflush(stdout); // sync stdout... 
		
		// Set pipes to stdin and stdout
		if( dup2( opipe[0], STDIN_FILENO ) < 0 )
			exit( 0 );
		if( dup2( ipipe[1], STDOUT_FILENO ) < 0 )
			exit( 0 );
		// Close unused ends of pipes
		close( opipe[1] );
		close( ipipe[0] );
		
		// Set Current Working Directory to that of script
		chdir( PWD.Path() );
		
		// Execute CGI in this process by means of /bin/sh 
		execve( args[0], args, env.GetEnvironment() );
		exit( 0 ); // If for some reason execve() fails...
	}
	else if( pid < (pid_t)0 ) // Something Bad happened!
	{
		close( opipe[0] );
		close( opipe[1] );
		close( ipipe[0] );
		close( ipipe[1] );
		response.SetHTMLMessage( 500, "Fork failed!" );
		pb->request->SendReply( &response );
		return true;
	}
	// Close unused ends of pipes
	close( opipe[0] );
	close( ipipe[1] );
	
	// ****
	// Talk to CGI
	// ****
	
	bool		persistant = true;
	
	// Defined to make code easier to read
	int			inDes = ipipe[0]; // input file descripter
	int			outDes = opipe[1]; // output file descripter
	
	// Make a BDataIO wrapper for the in and out pipes
	DesIO		pipeIO( inDes, outDes );
	
	// If the request contains a content body, feed it into stdin of the CGI script
	if( pb->request->GetContentLength() > 0 )
		pb->request->SendBody( &pipeIO );
	
	// Buffer the response body for better performance
	response.SetBodyBuffering( true );
	
	// Read first line to detect use of Non-Parsed Header Output
	io_getline( &pipeIO, headBuffer, fieldSize );
	
	// Strip the '\r' character if there is one
	int32	size;
	size = strlen( headBuffer )-1;
	if( headBuffer[size] == '\r' )
		headBuffer[size] = 0;
	
	// Is NPH Output?
	if( strncmp( "HTTP/", headBuffer, 5 ) == 0 )
	{
		DataIOPump		ioPump;
		BufferedIO		bufio( pb->request->GetReplyIO() );
		bufio.DoAllocate();
		
		io_printf( &bufio, "%s\r\n", headBuffer );
		ioPump.StartPump( &pipeIO, &bufio, contentLength );
		bufio.Flush();
		persistant = false;
	}
	else // using Parsed Header Output
	{
		// Add Date header
		time_t			now;
		struct tm 		*brokentime;
		
		now = time( NULL );
		brTimeLock.Lock();
		brokentime = gmtime( &now );
		strftime (fieldValue, 256, kHTTP_DATE, brokentime);
		brTimeLock.Unlock();
		
		response.AddHeader( kHEAD_DATE, fieldValue );
		
		// Add line used to detect NPH as CGI header
		response.AddHeader( headBuffer );
		
		// Receive the CGI headers
		response.ReceiveHeaders( &pipeIO );
			
		// If Location header, don't expect any more headers
		if( (sPtr = response.FindHeader( "Location", fieldValue, fieldSize )) )
		{
			response.SetStatusLine( 302 ); // 302 Moved Temporarily
		}
		else
		{
			if( (sPtr = response.FindHeader( "Status", fieldValue, fieldSize )) )
			{
				response.RemoveHeader( (char *)sPtr ); // Don't forward to client
				response.SetStatusLine( fieldValue );
			}
			else
				response.SetStatusLine( 200 );
		}
		
		// Don't cache the response
		if( !response.FindHeader( "Cache-Control", fieldValue, fieldSize ) )
			response.AddHeader( "Cache-Control: no-cache" );
		if( !response.FindHeader( "Pragma", fieldValue, fieldSize ) )
			response.AddHeader( "Pragma: no-cache" );
		
		// Content-Length header?
		int32		contentLength = 0;
		
		if( (sPtr = response.FindHeader( kHEAD_LENGTH, fieldValue, fieldSize )) )
		{
			contentLength = strtol( fieldValue, (char **)&headBuffer, 10 );
			response.SetContentLength( contentLength );
		}
		else // No content-length provided; close connection on return
		{
			response.AddHeader( "Connection: close" );
			persistant = false;
		}
		
		pb->Logprintf( "%ld Status-Line: %s\n", pb->sn, response.GetStatusLine() );
		if( pb->request->GetMethod() != METHOD_HEAD )
			response.SetMessageBody( &pipeIO );
		pb->request->SendReply( &response );
	}
	
	// Close remaining ends of pipes
	close( ipipe[0] );
	close( opipe[1] );
	pb->closeConnection = !persistant;
	return B_OK;
}