/**
 * Title:        Runtime Client - Server Java Project<p>
 * Description:  This is a client - server application that uses the Java
 * Runtime class to have commands executed on a server.
 *
 * The Server.java program creates 3 classes, Server.class,
 * ServerConnection.class, and Process_Request.class.
 *
 * The Client.java programs creates 3 classes, Client.class, Listener.class, and
 * ClientComm.class.
 *
 * The Server is a multi-threaded server which allows multiple clients to
 * connect and processes all commands by the client in seperate threads.
 *
 * The Client is a simple user input interface which creates a socket connection
 * to the Server and then sends the input command to the Server. It uses the
 * Listener.class, which is a thread, to recieve the output from the server and 
 * print the output to screen.
 *
 * To run, the Server.java file needs to be placed on one system, preferably a
 * UNIX machine. It then needs to be compiled using "javac Server.java" and
 * then started by the following: "java Server [port number] &"
 * The [port number] should be replaced by the port number that the server will
 * use for the socket connection. If none is specified the default of 8000 is used.
 * The "&" is used so that the process runs in the background.
 *
 * The Client.java now needs to be compiled on a seperate system.  After being
 * compiled, to run, type "java Client [server DNS name or IP address] [port]"
 * You will need to replace the [server DNS name ... etc.] with either the DNS
 * name or IP address of the system the Server.class is running on, and [port]
 * should be replaced with the port number that the Server.class is using. You
 * can now type in standard UNIX commands in on the client to be executed. To
 * quit the Client application, type "bye" as the command.
 * <p>
 * Copyright:    Copyright (c) Brian Summers, John Rountree, and Chriss Flynn<p>
 * Company:      none<p>
 * @author Brian Summers, John Rountree, and Chriss Flynn
 * @version 1.0
 */
//package clientserver;

import java.lang.*;
import java.io.*;
import java.net.*;

class Server {

	//Accepts a command line argument that contains the port number to use
	public static void main( String[] argv ) throws IOException {
		int port_number;
		
		//sets the default port to 8000 if none is specified
		if ( argv.length == 1 ) {
			if ( Integer.parseInt(argv[0]) < 1024 ) {
				port_number = 8000;
			}
			else {
			//sets the port number to the comand line argument
			port_number = Integer.parseInt(argv[0]);
			}
		}
		else {
			port_number = 8000;
		}

		try {
			//creates new server socket using above port number
			ServerSocket ss = new ServerSocket( port_number );

			//start the new server connection to the client
			while( true )
				new ServerConnection( ss.accept() ).start();
		} catch (BindException e) {
			System.out.println("Socket " + port_number + " already in use.");
			System.exit(1);
		}
	}
}


class ServerConnection extends Thread {
	public Socket client;
	
	ServerConnection ( Socket client ) throws SocketException {
		this.client = client;
		
		//sets the priority of the thread to 1 less then the normal
		setPriority( NORM_PRIORITY -1 );
	}

	public void run() {

		try {
			//creates BufferedReader to get command from the client
			BufferedReader in = new BufferedReader( new InputStreamReader( client.getInputStream() ) );

			//creates PrintWriter to send output to the client
			PrintWriter out = new PrintWriter( client.getOutputStream(), true );
	
			//creates a string
			String inputLine;
			
			//prints to System.out that a client has connected to it
			System.out.println("Connection made: " + client );

			//prints to client that the Connection has been made
			out.println("Connection Opened");


			while( true ) {

				//reads from the client and sets that command to the string
				while ( true  ) {
					inputLine = in.readLine();

					//waits until the string is not equal to null or ""
					//may not be needed
					while( (inputLine == null) || (inputLine == "") ) {
					}
					break;
				}
	
				//does not work properly. Was to be used in conjunction with
				//the client to stop the reading in of new commands
				if ( inputLine == "bye" )
					break;

				//creates and starts Process_Request object to process the command
				Process_Request pq = new Process_Request(inputLine, out);
				pq.start();
			}
			//closes the input and output streams to the client
			out.close();
			in.close();
		} catch ( IOException e1 ) {
		System.out.println("IO Error: " + e1);
		}
		
		try {
			client.close();
		} catch (IOException e2 ) {  
		System.out.println("Error closing connection to client: " + client );
		}
	}
}


class Process_Request extends Thread {
	public String command;
	public Process output;
	public Socket client;
	public PrintWriter out;

	public Process_Request(String args, PrintWriter out_stream) {
		command = args;
		out = out_stream;

		//sends output to the client if the command is null
		if (command == null) {
			out.println("Command Read Error. Command not executed.");
		}
	}

	public void run() {
		
		try {
			//create new process object with is created from runtime.exec()
			Process proc = Runtime.getRuntime().exec(command);
			
			//creates new datainputstream object to read from the process
			DataInputStream din = new DataInputStream(proc.getInputStream());
			String response = din.readLine();

			//prints all the output from the process to the client
			while( response != null  ) {
				out.println(response);
				response = din.readLine();
			}

		} catch ( IOException e ) {
		System.out.println("Runtime IO error: " + e);
		out.println("Runtime IO Error: " + e);
		}
	}
}

