//============================================================================== // FTPCommandInterpreter.java //============================================================================== package tribble.net.ftp.shell; // System imports import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.InputStreamReader; import java.io.IOException; import java.io.Reader; import java.io.PrintStream; import java.io.PrintWriter; import java.lang.Exception; import java.lang.String; import java.lang.System; import java.text.ParseException; /******************************************************************************* * Rattlesnake FTP command interpreter. * Reads, compiles, and executes FTP commands from a command script. * *

* * Usage *

* * java tribble.net.ftp.shell.FTPCommandInterpreter * [-option...] file * * *

* * Options * *

*
-Dp *
Debug: display the compiled parse tree. * *

*

-e file *
Error output file. By default, all output is written to the standard * error output stream. * *

*

-Le *
Limit the execution to only 1,000 commands. * *

*

-ne *
Do not execute, only compile the command script. * *

*

-o file *
Output file. By default, all output is written to the standard * output stream. * *

*

-v *
Generate verbose output during execution. * * *
* *

* The file is a script containing FTP commands. * Note that the entire command file is read and parsed into memory before any * commands are executed. * See the package summary for details about * using command files. * * * @version $Revision: 1.6 $ $Date: 2007/08/12 18:35:26 $ * @since API 1.0, 2007-04-05 * @author David R. Tribble (david@tribble.com). *

* Copyright ©2007 by David R. Tribble, all rights reserved.
* Permission is granted to any person or entity except those designated by * by the United States Department of State as a terrorist, or terrorist * government or agency, to use and distribute this source code provided * that the original copyright notice remains present and unaltered. *

* If you find this software useful, please drop me a note describing how * you used it. */ public class FTPCommandInterpreter { // Identification /** Revision information. */ static final String REV = "@(#)tribble/net/ftp/shell/FTPCommandInterpreter.java $Revision: 1.6 $ $Date: 2007/08/12 18:35:26 $\n"; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Static variables /** Standard input stream. */ static Reader s_stdin = new InputStreamReader(System.in); /** Standard output stream. */ static PrintWriter s_stdout = new PrintWriter(System.out, true); /** Standard error output stream. */ static PrintWriter s_stderr = new PrintWriter(System.err, true); /** FTP command interpreter shell. */ static FTPCommandInterpreter s_shell; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Static methods /*************************************************************************** * FTP command script interpreter. * *

* Usage: see Usage above. * * @since 1.1, 2007-04-05 */ public static void main(String[] args) throws Exception { int rc; // Create and run an FTP command interpreter s_shell = new FTPCommandInterpreter(); rc = s_shell.run(args); // Done s_shell = null; System.exit(rc); } /*************************************************************************** * Stop the currently running FTP command script interpreter. * *

* This method may be used when the FTP interpreter is being run as a daemon * or service program (i.e., a continuously running process) in order to * signal it to terminate cleanly. * * @since 1.3, 2007-05-05 */ public static void stop() { FTPCommandInterpreter shell; // Stop the currently running interpreter shell = s_shell; if (shell != null) { Interp interp; interp = shell.m_interp; if (interp != null) interp.stop(); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Variables /** Standard input stream. */ Reader m_in = s_stdin; /** Standard output stream. */ PrintStream m_outS = System.out; /** Standard output stream. */ PrintWriter m_out = s_stdout; /** Standard error output stream. */ PrintStream m_errS = System.err; /** Standard error output stream. */ PrintWriter m_err = s_stderr; /** FTP command interpreter. */ Interp m_interp; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructors /*************************************************************************** * Default constructor. * * @since 1.3, 2007-05-05 */ private FTPCommandInterpreter() { // Initialize } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Methods /*************************************************************************** * FTP command script interpreter. * *

* Usage: see Usage above. * * @since 1.3, 2007-05-05 */ int run(String[] args) throws Exception { String fname = null; String outFname = "-"; String errFname = "-"; boolean printBlocks = false; boolean printTree = false; boolean verbose = false; boolean noExec = false; boolean limitExec = false; int i; // Check args for (i = 0; i < args.length && args[i].charAt(0) == '-'; i++) { if (args[i].equals("-")) break; else if (args[i].equals("-Db")) printBlocks = true; else if (args[i].equals("-Dp")) printTree = true; else if (args[i].equals("-e")) errFname = args[++i]; else if (args[i].equals("-Le")) limitExec = true; else if (args[i].equals("-ne")) noExec = true; else if (args[i].equals("-o")) outFname = args[++i]; else if (args[i].equals("-v")) verbose = true; else i = args.length; } // Check usage if (i >= args.length) { // Display a usage message s_stdout.println("Execute an FTP command script file."); s_stdout.println(); s_stdout.println("usage: java " + FTPCommandInterpreter.class.getName() + " [-option...] file"); s_stdout.println(); s_stdout.println("Options:"); s_stdout.println(" -Db " + "Debug: display the compiled block definitions."); s_stdout.println(" -Dp " + "Debug: display the compiled parse tree."); s_stdout.println(" -e file " + "Error output file (default is standard error output)."); s_stdout.println(" -Le " + "Limit the execution to only 1,000 commands."); s_stdout.println(" -ne " + "Do not execute, only compile the command script."); s_stdout.println(" -o file " + "Output file (default is standard output)."); s_stdout.println(" -v " + "Generate verbose output during execution."); /***+INCOMPLETE s_stdout.println(" -D " + "Enable debug traces."); s_stdout.println(" -D- " + "Disable debug traces"); s_stdout.println(" -I " + "Ignore exceptions."); s_stdout.println(" -I- " + "Terminate if an exception occurs (default)."); s_stdout.println(" -mn " + "Non-passive mode, client chooses data ports."); s_stdout.println(" -mp " + "Passive mode, remote server chooses data ports."); s_stdout.println(" -p cport[:dport]" + "Command and data port numbers"); s_stdout.println(" -u user " + "User-ID"); +++*/ // Punt System.exit(255); } // Open the output stream if (!outFname.equals("-")) { m_outS = new PrintStream(new FileOutputStream(outFname), true); m_out = new PrintWriter(m_outS, true); } // Open the error output stream if (!errFname.equals("-")) { m_errS = new PrintStream(new FileOutputStream(errFname), true); m_err = new PrintWriter(m_errS, true); } // Open, compile, and execute the command script try { CommandParser parser; CommandNode cmds; int rc = 0; // Open the command input stream fname = args[i]; if (fname.equals("-")) m_in = s_stdin; else m_in = new FileReader(fname); // Compile the command script file parser = new CommandParser(m_in, m_out); parser.setSourceName(fname); cmds = parser.parse(); if (parser.m_nErrors + parser.m_nWarnings > 0) { m_out.println(fname + ": Errors: " + parser.m_nErrors + ", warnings: " + parser.m_nWarnings); m_out.println(); m_out.flush(); } if (printBlocks) { BlockDef blk; // Print the resulting block definitions m_out.println("Program blocks:"); if (cmds != null) { blk = (BlockDef) cmds.m_args[0]; blk.printTree(m_out); } else m_out.println(""); m_out.println(); m_out.flush(); } if (printTree) { // Print the resulting parse tree m_out.println("Parse tree:"); if (cmds != null) cmds.print(m_out); else m_out.println(""); m_out.println(); m_out.flush(); } // Execute (interpret) the parsed commands if (!noExec && cmds != null) { long msec; String time; int t; // Execute the compiled commands if (verbose || printBlocks || printTree) m_out.println("Execution:"); m_interp = new Interp(cmds, m_outS, m_errS); m_interp.m_verbose = verbose; m_interp.m_limitCmds = limitExec; rc = m_interp.execute(); // Display a summary of the execution msec = m_interp.m_time - m_interp.m_startTime; if (msec < 60*60*1000) time = msec/1000 + ""; else { long m; m = msec/1000; // secs t = (int) (m%60); time = (t < 10 ? ":0" : ":") + t; m = m/60; // mins t = (int) (m%60); time = (t < 10 ? ":0" : ":") + t + time; m = m/60; // hours t = (int) (m%24); time = t + time; if (m > 24) { time = (t < 10 ? "0" : "") + time; m = m/24; // days t = (int) m; time = t + "d " + time; } } t = (int) msec%1000; // msec time += "." + (t < 10 ? "00" : t < 100 ? "0" : "") + t; if (verbose) { m_out.println(); m_out.print("Commands: " + m_interp.m_nExecs); m_out.print(", time: " + time); m_out.println(", exit: " + rc); } m_interp = null; } else m_out.println("*** Execution cancelled"); // Done return (rc); } catch (ParseException ex) { // Compile error m_out.println(fname + ":" + ex.getErrorOffset() + ": error: " + ex.getMessage()); m_out.flush(); return (1); } finally { // Clean up m_out.flush(); if (m_out != s_stdout) m_out.close(); if (m_in != null && m_in != s_stdin) m_in.close(); } } } // End FTPCommandInterpreter.java