client/ftpd/src/se/lu/thep/coreftpd/webserver/RunScript.java

Code
Comments
Other
Rev Date Author Line
741 10 Oct 06 olle 1 /*
1652 22 May 07 gregory 2  $Id$
741 10 Oct 06 olle 3
1916 31 Aug 07 jari 4  Copyright (C) 2006 Olle Mansson
1916 31 Aug 07 jari 5  Copyright (C) 2007 Gregory Vincic
741 10 Oct 06 olle 6
1652 22 May 07 gregory 7  This file is part of Proteios.
1652 22 May 07 gregory 8  Available at http://www.proteios.org/
741 10 Oct 06 olle 9
1652 22 May 07 gregory 10  Proteios is free software; you can redistribute it and/or modify it
1652 22 May 07 gregory 11  under the terms of the GNU General Public License as published by
1652 22 May 07 gregory 12  the Free Software Foundation; either version 2 of the License, or
1652 22 May 07 gregory 13  (at your option) any later version.
741 10 Oct 06 olle 14
1652 22 May 07 gregory 15  Proteios is distributed in the hope that it will be useful, but
1652 22 May 07 gregory 16  WITHOUT ANY WARRANTY; without even the implied warranty of
1652 22 May 07 gregory 17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1652 22 May 07 gregory 18  General Public License for more details.
741 10 Oct 06 olle 19
1652 22 May 07 gregory 20  You should have received a copy of the GNU General Public License
1652 22 May 07 gregory 21  along with this program; if not, write to the Free Software
1652 22 May 07 gregory 22  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1652 22 May 07 gregory 23  02111-1307, USA.
1652 22 May 07 gregory 24  */
741 10 Oct 06 olle 25
741 10 Oct 06 olle 26 //  Xerver Free Web Server
741 10 Oct 06 olle 27 //  Copyright (C) 2002-2005 Omid Rouhani
741 10 Oct 06 olle 28 //
741 10 Oct 06 olle 29 //
741 10 Oct 06 olle 30 //  This program is free software; you can redistribute it and/or
741 10 Oct 06 olle 31 //  modify it under the terms of the GNU General Public License
741 10 Oct 06 olle 32 //  as published by the Free Software Foundation; either version 2
741 10 Oct 06 olle 33 //  of the License, or (at your option) any later version.
741 10 Oct 06 olle 34 //
741 10 Oct 06 olle 35 //  This program is distributed in the hope that it will be useful,
741 10 Oct 06 olle 36 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
741 10 Oct 06 olle 37 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
741 10 Oct 06 olle 38 //  GNU General Public License for more details.
741 10 Oct 06 olle 39 //
741 10 Oct 06 olle 40 //  You should have received a copy of the GNU General Public License
741 10 Oct 06 olle 41 //  along with this program; if not, write to the Free Software
741 10 Oct 06 olle 42 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
741 10 Oct 06 olle 43 //
741 10 Oct 06 olle 44 //
741 10 Oct 06 olle 45 //  #############################################################
741 10 Oct 06 olle 46 //  ##  YOU CAN CONTACT THE AUTHOR (OMID ROUHANI) AT:          ##
741 10 Oct 06 olle 47 //  ##  HTTP://WWW.JAVASCRIPT.NU/XERVER/                       ##
741 10 Oct 06 olle 48 //  ##                                                         ##
741 10 Oct 06 olle 49 //  ##  IF YOUR SOFTWARE IS NOT RELEASED UNDER THE             ##
741 10 Oct 06 olle 50 //  ##  GNU GENERAL PUBLIC LICENSE (GPL),                      ##
741 10 Oct 06 olle 51 //  ##  PLEASE DO NOT COPY ANYTHING FROM THIS SOURCE CODE!!!   ##
741 10 Oct 06 olle 52 //  ##                                                         ##
741 10 Oct 06 olle 53 //  ##  FOR FULL LICENSE, PLEASE READ "XERVER LICENSE".        ##
741 10 Oct 06 olle 54 //  #############################################################
741 10 Oct 06 olle 55
1652 22 May 07 gregory 56 package se.lu.thep.coreftpd.webserver;
741 10 Oct 06 olle 57
791 23 Oct 06 olle 58 import se.lu.thep.coreftpd.common.DataInputStreamWithReadLine;
791 23 Oct 06 olle 59 import se.lu.thep.coreftpd.common.MyInteger;
741 10 Oct 06 olle 60 import java.io.BufferedInputStream;
741 10 Oct 06 olle 61 import java.io.BufferedOutputStream;
741 10 Oct 06 olle 62 import java.io.DataOutputStream;
741 10 Oct 06 olle 63 import java.io.File;
741 10 Oct 06 olle 64 import java.io.OutputStream;
741 10 Oct 06 olle 65
741 10 Oct 06 olle 66 /**
1652 22 May 07 gregory 67  * 
1652 22 May 07 gregory 68  * <B>How to use:</B> <BR>
1652 22 May 07 gregory 69  * <CODE>(new RunScript(String command, OutputStream argFos, String []
1652 22 May 07 gregory 70  * environmentVariablesString, DataInputStreamWithReadLine DISWR_POSTData,
1652 22 May 07 gregory 71  * String s_scriptLocation, NewConnection NC_theNewConnection)).start();</CODE>
741 10 Oct 06 olle 72  * <BR>
741 10 Oct 06 olle 73  * <BR>
1652 22 May 07 gregory 74  * 
1652 22 May 07 gregory 75  * <B>More info:</B> <BR>
1652 22 May 07 gregory 76  * This class gets a command and runs it. STDOUT and STDERR from the script is
1652 22 May 07 gregory 77  * sent to an <CODE>argFos</CODE>. <BR>
741 10 Oct 06 olle 78  * <BR>
1652 22 May 07 gregory 79  * 
1652 22 May 07 gregory 80  * <CODE>command</CODE> = a command (IMPORTANT: a command in java is NOT a
1652 22 May 07 gregory 81  * command you give in the prompt, but it's a runnable program. For example:
1652 22 May 07 gregory 82  * [Wrong: "script.pl"; Correct: "perl script.pl"] (it doesn't matter that you
1652 22 May 07 gregory 83  * in a prompt only have to write "script.pl")) <BR>
1652 22 May 07 gregory 84  * <CODE>argFos</CODE> = the output will be written to this <BR>
1652 22 May 07 gregory 85  * <CODE>environmentVariablesString</CODE> = an array of <CODE>String</CODE>s:
1652 22 May 07 gregory 86  * "envVar=envValue" <BR>
1652 22 May 07 gregory 87  * <CODE>DISWR_POSTData</CODE> = this will be sent to standard input (if this
1652 22 May 07 gregory 88  * is <CODE>==null</CODE>, nothing will be sent to STDIN). <BR>
1652 22 May 07 gregory 89  * <CODE>argScriptLocation</CODE> = Location of script as browser path
1652 22 May 07 gregory 90  * ("http://server.com/dir1/dir2/file.pl" ==> "/dir1/dir2/") <BR>
1652 22 May 07 gregory 91  * <CODE>NC_theNewConnection</CODE> = this shall be the <CODE>NewConnection</CODE>
1652 22 May 07 gregory 92  * that belongs to the specific request that started RunScript. We need this to
1652 22 May 07 gregory 93  * change the value off <CODE>s_errorStatus</CODE> to "500 Internal Server
1652 22 May 07 gregory 94  * Error" and to run <CODE>addThisHitToLog()</CODE>.
1652 22 May 07 gregory 95  * 
741 10 Oct 06 olle 96  * <BR>
1652 22 May 07 gregory 97  * 
741 10 Oct 06 olle 98  * @author <a href="http://www.JavaScript.nu/xerver/" TARGET="_top">Omid Rouhani</a>
741 10 Oct 06 olle 99  * @version 1.0
741 10 Oct 06 olle 100  */
741 10 Oct 06 olle 101
1652 22 May 07 gregory 102 final public class RunScript extends Thread {
1652 22 May 07 gregory 103   private final static boolean b_showErrors = false;
741 10 Oct 06 olle 104
1652 22 May 07 gregory 105   private BufferedInputStream bis; // Get data from script from this
1652 22 May 07 gregory 106                     // (STDOUT)
741 10 Oct 06 olle 107
1652 22 May 07 gregory 108   private BufferedInputStream bes; // Get errors from script from this
1652 22 May 07 gregory 109                     // (STDERR)
741 10 Oct 06 olle 110
1652 22 May 07 gregory 111   private BufferedOutputStream bos; // Send data to script with this (for
1652 22 May 07 gregory 112                     // example when POST-data has been sent)
741 10 Oct 06 olle 113
1652 22 May 07 gregory 114   MyInteger whoShallRespond = new MyInteger(ReadInputStream.RESPOND_UNDEFINED);
1652 22 May 07 gregory 115
1652 22 May 07 gregory 116   private int i_timeToKillScript = 60 * 60 * 1000; // One hour before we
1652 22 May 07 gregory 117                             // kill process
1652 22 May 07 gregory 118
741 10 Oct 06 olle 119   private Process proc;
741 10 Oct 06 olle 120
1652 22 May 07 gregory 121   // private static int i_numberRunScriptsRunning=0;
1652 22 May 07 gregory 122   // private static int i_numberRunScriptsNotFinalized=0;
741 10 Oct 06 olle 123
1652 22 May 07 gregory 124   public RunScript(String command, OutputStream argFos,
1652 22 May 07 gregory 125       String[] environmentVariablesString,
1652 22 May 07 gregory 126       DataInputStreamWithReadLine DISWR_POSTData,
1652 22 May 07 gregory 127       String s_scriptLocation, String s_documentToReturn,
1652 22 May 07 gregory 128       NewConnection NC_theNewConnection) {
1652 22 May 07 gregory 129     // i_numberRunScriptsRunning++;
1652 22 May 07 gregory 130     // i_numberRunScriptsNotFinalized++;
741 10 Oct 06 olle 131
741 10 Oct 06 olle 132     try {
741 10 Oct 06 olle 133       Runtime run;
1652 22 May 07 gregory 134       DataOutputStream fos; // FileOutputStream
741 10 Oct 06 olle 135       run = Runtime.getRuntime();
1652 22 May 07 gregory 136       proc = run.exec(command, environmentVariablesString, new File(
1652 22 May 07 gregory 137           s_documentToReturn).getParentFile()); // Make sure the
1652 22 May 07 gregory 138                               // script is running
1652 22 May 07 gregory 139                               // with PWD to the
1652 22 May 07 gregory 140                               // correct directory
1652 22 May 07 gregory 141       fos = new DataOutputStream(argFos);
741 10 Oct 06 olle 142
1652 22 May 07 gregory 143       bis = new BufferedInputStream(proc.getInputStream());
1652 22 May 07 gregory 144       bes = new BufferedInputStream(proc.getErrorStream());
1652 22 May 07 gregory 145       bos = new BufferedOutputStream(proc.getOutputStream());
741 10 Oct 06 olle 146
741 10 Oct 06 olle 147       ReadInputStreamSTDERR stdErrThread;
1652 22 May 07 gregory 148       (stdErrThread = new ReadInputStreamSTDERR(bes, fos,
1652 22 May 07 gregory 149           s_scriptLocation, NC_theNewConnection, whoShallRespond,
1652 22 May 07 gregory 150           this)).start(); // Don't write Location and Content-Type
1652 22 May 07 gregory 151       (new ReadInputStreamSTDOUT(bis, fos, s_scriptLocation,
1652 22 May 07 gregory 152           NC_theNewConnection, stdErrThread, whoShallRespond, this))
1652 22 May 07 gregory 153           .start(); // Don't write Location and Content-Type
741 10 Oct 06 olle 154
1652 22 May 07 gregory 155       if (DISWR_POSTData != null) {
741 10 Oct 06 olle 156         (new ReadInputStreamSTDIN(DISWR_POSTData, bos, this)).start();
741 10 Oct 06 olle 157       }
741 10 Oct 06 olle 158
741 10 Oct 06 olle 159       RunKiller rk_killer = new RunKiller(proc, fos, i_timeToKillScript);
1652 22 May 07 gregory 160       rk_killer.start(); // Kill process after 5*60 seconds
741 10 Oct 06 olle 161
741 10 Oct 06 olle 162       proc.waitFor();
741 10 Oct 06 olle 163
1652 22 May 07 gregory 164     } catch (Exception e) {
1652 22 May 07 gregory 165       if (b_showErrors)
1652 22 May 07 gregory 166         System.out.println("An error has occured @ RunScript:\n"
1652 22 May 07 gregory 167             + e.getMessage());
1652 22 May 07 gregory 168     }
741 10 Oct 06 olle 169
1652 22 May 07 gregory 170     // i_numberRunScriptsRunning--;
741 10 Oct 06 olle 171
1652 22 May 07 gregory 172     // System.out.println("RunScript running: "+i_numberRunScriptsRunning);
1652 22 May 07 gregory 173     // System.out.println("RunScript running (finalized):
1652 22 May 07 gregory 174     // "+i_numberRunScriptsNotFinalized);
741 10 Oct 06 olle 175   }
741 10 Oct 06 olle 176
1652 22 May 07 gregory 177   public void killProcess() {
1652 22 May 07 gregory 178     if (proc != null) {
741 10 Oct 06 olle 179       proc.destroy();
1652 22 May 07 gregory 180       proc = null;
741 10 Oct 06 olle 181     }
741 10 Oct 06 olle 182   }
741 10 Oct 06 olle 183
1652 22 May 07 gregory 184   // Testing...
2386 14 Nov 07 gregory 185   @Override
1652 22 May 07 gregory 186   protected void finalize() throws Throwable {
1652 22 May 07 gregory 187     // i_numberRunScriptsNotFinalized--;
741 10 Oct 06 olle 188
1652 22 May 07 gregory 189     if (bos != null) {
741 10 Oct 06 olle 190       bos.flush();
741 10 Oct 06 olle 191       bos.close();
1652 22 May 07 gregory 192       bos = null;
741 10 Oct 06 olle 193     }
1652 22 May 07 gregory 194     if (bes != null) {
741 10 Oct 06 olle 195       bes.close();
1652 22 May 07 gregory 196       bes = null;
741 10 Oct 06 olle 197     }
1652 22 May 07 gregory 198     if (bis != null) {
741 10 Oct 06 olle 199       bis.close();
1652 22 May 07 gregory 200       bis = null;
741 10 Oct 06 olle 201     }
1652 22 May 07 gregory 202     if (proc != null) {
741 10 Oct 06 olle 203       proc.destroy();
1652 22 May 07 gregory 204       proc = null;
741 10 Oct 06 olle 205     }
741 10 Oct 06 olle 206   }
741 10 Oct 06 olle 207 }