Log.warn("Non-zero exit status ("+exitValue+") from CGI program: "+path); if (!res.isCommitted()) res.sendError(500, "Failed to exec CGI");
int exitValue = p.exitValue(); if (0 != exitValue) { Log.warn("Non-zero exit status ("+exitValue+") from CGI program: "+path); if (!res.isCommitted()) res.sendError(500, "Failed to exec CGI"); }
  private void exec( File command, String pathInfo,                     HttpServletRequest req, HttpServletResponse res)               throws IOException  {    String path = command.getAbsolutePath();    File dir = command.getParentFile();    String scriptName = req.getRequestURI().substring(0,req.getRequestURI().length() - pathInfo.length());    String scriptPath = getServletContext().getRealPath(scriptName);    String pathTranslated = req.getPathTranslated();        int len = req.getContentLength();    if (len < 0) len = 0;    if ((pathTranslated == null) || (pathTranslated.length() == 0))      pathTranslated = path;          EnvList env = new EnvList(_env);    // these ones are from "The WWW Common Gateway Interface Version 1.1"    // look at : http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1    env.set("AUTH_TYPE", req.getAuthType());    env.set("CONTENT_LENGTH", Integer.toString(len));    env.set("CONTENT_TYPE", req.getContentType());    env.set("GATEWAY_INTERFACE", "CGI/1.1");    if ((pathInfo != null) && (pathInfo.length() > 0))    {      env.set("PATH_INFO", pathInfo);    }    env.set("PATH_TRANSLATED", pathTranslated);    env.set("QUERY_STRING", req.getQueryString());    env.set("REMOTE_ADDR", req.getRemoteAddr());    env.set("REMOTE_HOST", req.getRemoteHost());    // The identity information reported about the connection by a    // RFC 1413 [11] request to the remote agent, if    // available. Servers MAY choose not to support this feature, or    // not to request the data for efficiency reasons.    // "REMOTE_IDENT" => "NYI"    env.set("REMOTE_USER", req.getRemoteUser());    env.set("REQUEST_METHOD", req.getMethod());    env.set("SCRIPT_NAME", scriptName);    env.set("SCRIPT_FILENAME", scriptPath);    env.set("SERVER_NAME", req.getServerName());    env.set("SERVER_PORT", Integer.toString(req.getServerPort()));    env.set("SERVER_PROTOCOL", req.getProtocol());    env.set("SERVER_SOFTWARE", getServletContext().getServerInfo());    Enumeration enm = req.getHeaderNames();    while (enm.hasMoreElements())    {      String name = (String) enm.nextElement();      String value = req.getHeader(name);      env.set("HTTP_" + name.toUpperCase().replace( '-', '_' ), value);    }    // these extra ones were from printenv on www.dev.nomura.co.uk    env.set("HTTPS", (req.isSecure() ? "ON" : "OFF"));    // "DOCUMENT_ROOT" => root + "/docs",    // "SERVER_URL" => "NYI - http://us0245",    // "TZ" => System.getProperty("user.timezone"),    // are we meant to decode args here ? or does the script get them    // via PATH_INFO ?  if we are, they should be decoded and passed    // into exec here...    String execCmd = path;    if ((execCmd.charAt(0) != '"') && (execCmd.indexOf(" ") >= 0))      execCmd="\""+execCmd+"\"";    if (_cmdPrefix != null)      execCmd = _cmdPrefix+" "+execCmd;    Process p = (dir==null) ? Runtime.getRuntime().exec(execCmd, env.getEnvArray())                            : Runtime.getRuntime().exec(execCmd, env.getEnvArray(),dir);    // hook processes input to browser's output (async)    final InputStream inFromReq = req.getInputStream();    final OutputStream outToCgi = p.getOutputStream();    final int inLength = len;    new Thread(new Runnable()    {      public void run()      {        try        {          if (inLength > 0)            IO.copy(inFromReq, outToCgi, inLength);          outToCgi.close();        }        catch(IOException e){Log.ignore(e);}      }    }).start();    // hook processes output to browser's input (sync)    // if browser closes stream, we should detect it and kill process...    BufferedReader br = null;    PrintWriter writer = null;    try    {      // read any headers off the top of our input stream      // NOTE: Multiline header items not supported!      String line = null;      InputStream inFromCgi = p.getInputStream();      br = new BufferedReader(new InputStreamReader(inFromCgi));      while((line = br.readLine()) != null)      {        // check for end of header        if (line.trim().length() == 0) break;        if (!line.startsWith("HTTP"))        {          int k = line.indexOf(':');          if (k > 0)          {            String key = line.substring(0,k).trim();            if ("Location".equals(key))            {              res.sendRedirect(line.substring(k+1).trim());            }            else if ("Status".equals(key))            {              int status = Integer.parseInt(line.substring(k+1).trim());              res.setStatus(status);            }            else            {              // add remaining header items to our response header              res.addHeader(key, line.substring(k+1));            }          }        }      }      // copy cgi content to response stream...      writer = res.getWriter();      IO.copy(br, writer);      p.waitFor();      int exitValue = p.exitValue();      if (0 != exitValue)      {        Log.warn("Non-zero exit status ("+exitValue+") from CGI program: "+path);        if (!res.isCommitted())          res.sendError(500, "Failed to exec CGI");      }    }    catch (IOException e)    {      // browser has probably closed its input stream - we      // terminate and clean up...      Log.debug("CGI: Client closed connection!");    }    catch (InterruptedException ie)    {      Log.debug("CGI: interrupted!");    }    finally    {      if (br != null) try { br.close(); }catch(IOException ioe){}      if (writer != null) writer.close();      br = null;      writer = null;      p.destroy();//      Log.debug("CGI: terminated!");    }  }