diff --git a/src/main/java/JobServ/JobServClient.java b/src/main/java/JobServ/JobServClient.java index 0a041ac..2939c5d 100644 --- a/src/main/java/JobServ/JobServClient.java +++ b/src/main/java/JobServ/JobServClient.java @@ -54,8 +54,8 @@ public class JobServClient { try { return Integer.parseInt(this.programArgs[index]); - } catch (InputMismatchException e) { - System.out.println(this.programArgs[index] + " is not a valid int, much less a valid pid"); + } catch (NumberFormatException e) { + System.out.println(this.programArgs[index] + " is not a valid integer"); return -1; } @@ -69,9 +69,9 @@ public class JobServClient { System.out.println("... new (command)\n"+ "Starts a new process on the server\n"+ "example: ./client key.pem cert.crt ca.crt localhost 8448 new echo hello world!\n\n"+ - "... output (pid)\n"+ - "Garners output from process on server\n"+ - "example: ./client key.pem cert.crt ca.crt localhost 8448 output 0\n\n"+ + "... output (pid) (lines)\n"+ + "Garners (lines) lines of output from process (pid) on server\n"+ + "example: ./client key.pem cert.crt ca.crt localhost 8448 output 0 5\n\n"+ "... status (pid)\n"+ "Returns whether process on server is running"+ "example: ./client key.pem cert.crt ca.crt localhost 8448 status 0\n\n"+ @@ -88,11 +88,6 @@ public class JobServClient { * makes a new process */ public void makeNewProcess() { - if (this.programArgs.length < 6) { - System.out.println("Improper formatting, try client --help"); - return; - } - String command = ""; for (int token = 6; token < this.programArgs.length; token++) { command += " " + this.programArgs[token]; @@ -121,12 +116,18 @@ public class JobServClient { * gets output from a process */ public void getOutput() { + if (this.programArgs.length < 8) { + System.out.println("Improper formatting, need a lines and a pid argument."); + return; + } + int candidatePid = this.getPidArg(6); + int lines = this.getPidArg(7); if (candidatePid < 0) { return; } - String processOutput = this.api.getProcessOutput(candidatePid); + String processOutput = this.api.getProcessOutput(candidatePid, lines); System.out.println(processOutput); } diff --git a/src/main/java/JobServ/JobServClientAPIConnector.java b/src/main/java/JobServ/JobServClientAPIConnector.java index b8d50ef..2e4a02c 100644 --- a/src/main/java/JobServ/JobServClientAPIConnector.java +++ b/src/main/java/JobServ/JobServClientAPIConnector.java @@ -63,11 +63,12 @@ class JobServClientAPIConnector { * sends the server a request for output from the process identified by 'pid' * returns process output as string */ - public String getProcessOutput(int pid) { + public String getProcessOutput(int pid, int lines) { logger.info("[+] requesting output"); - PIDMessage request = PIDMessage.newBuilder() + OutputRequestMessage request = OutputRequestMessage.newBuilder() .setPid(pid) + .setLines(lines) .build(); OutputMessage response; diff --git a/src/main/java/JobServ/ProcessController.java b/src/main/java/JobServ/ProcessController.java index 69c3bbf..ce2d599 100644 --- a/src/main/java/JobServ/ProcessController.java +++ b/src/main/java/JobServ/ProcessController.java @@ -8,10 +8,11 @@ package JobServ; -import java.util.Scanner; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.BufferedReader; /* * ProcessController @@ -28,7 +29,8 @@ class ProcessController { // interactive processes (out of scope for initial API) private OutputStream output; private InputStream input; - private Scanner outputScanner; + private InputStreamReader inputIntermediateStream; + private BufferedReader reader; private Process process; @@ -46,8 +48,8 @@ class ProcessController { this.process = Runtime.getRuntime().exec(command); this.output = this.process.getOutputStream(); this.input = this.process.getInputStream(); - this.outputScanner = new Scanner(this.input); - this.outputScanner.useDelimiter("\\A"); + this.inputIntermediateStream = new InputStreamReader(this.input); + this.reader = new BufferedReader(this.inputIntermediateStream); } /* @@ -61,9 +63,6 @@ class ProcessController { /* * getStatus() * returns whether or not the process is running - * this isnt a very direct way of getting the information - * The alternative is to use reflection to get into the private UNIXProcess class - * for the PID and to check that against 'ps' or a similar command * * TODO: (for future release) return thread state */ @@ -85,7 +84,7 @@ class ProcessController { * returns the exit code of the process * 256 if process is still running * 257 if process was killed manually and no longer exists - * (unix/posix defines an exit code as a uint8, so 256 is fair game) + * (unix/posix defines an exit code as a uint8, so 256+ is fair game) */ public int getReturn() { if (this.killedManually) { @@ -103,17 +102,23 @@ class ProcessController { * getOutput() * gets output from process */ - public String getOutput() { - if (this.killedManually) { - return ""; + public String getOutput(int lines) { + String output = ""; + for (int i = 0; i < lines; i++) { + String newLine = null; + try { + newLine = reader.readLine(); + } catch (IOException e) { + newLine = "[-] SERVER: error reading process output: " + e.getMessage(); + } finally { + if (newLine != null) { + output += newLine + "\n"; + } + } + } - String out = ""; - while(outputScanner.hasNext()) { - out += outputScanner.next(); - } - - return out; + return output; } /* @@ -121,15 +126,20 @@ class ProcessController { * Cleans up resources and destroys process */ public void kill() { + if (this.killedManually) { + System.err.println("[~] Tried to kill already killed process"); + return; + } + try { this.input.close(); this.output.close(); - this.outputScanner.close(); + this.inputIntermediateStream.close(); + this.reader.close(); this.process.destroy(); + this.killedManually = true; } catch (IOException e) { - // streams already closed + System.err.println("[-] Killing process failed: " + e.getMessage()); } - - this.killedManually = true; } } diff --git a/src/main/java/JobServ/ProcessManager.java b/src/main/java/JobServ/ProcessManager.java index ebac0b8..c11650d 100644 --- a/src/main/java/JobServ/ProcessManager.java +++ b/src/main/java/JobServ/ProcessManager.java @@ -140,7 +140,7 @@ class ProcessManager { * returns output of process 'pid' * or returns description of error */ - public String getProcessOutput(int pid) { + public String getProcessOutput(int pid, int lines) { try { if(!this.getLock(pid)) { return "[-] SERVER: Process not found"; @@ -152,7 +152,7 @@ class ProcessManager { } ProcessController candidate = this.processMap.get(pid); - String output = candidate.getOutput(); + String output = candidate.getOutput(lines); this.releaseLock(pid); return output; } diff --git a/src/main/java/JobServ/ShellServerService.java b/src/main/java/JobServ/ShellServerService.java index 953b0e1..370557b 100644 --- a/src/main/java/JobServ/ShellServerService.java +++ b/src/main/java/JobServ/ShellServerService.java @@ -47,10 +47,11 @@ class ShellServerService extends ShellServerGrpc.ShellServerImplBase { * implements api endpoint as defined in jobserv.proto */ @Override - public void getOutput(PIDMessage request, + public void getOutput(OutputRequestMessage request, StreamObserver responder) { - String output = manager.getProcessOutput(request.getPid()); + String output = manager.getProcessOutput(request.getPid(), + request.getLines()); OutputMessage reply = OutputMessage.newBuilder() .setOutput(output) @@ -67,7 +68,8 @@ class ShellServerService extends ShellServerGrpc.ShellServerImplBase { public void newJob(NewJobMessage request, StreamObserver responder) { - int newPid = manager.newProcess(request.getCommand()); + String command = request.getCommand(); + int newPid = manager.newProcess(command); PIDMessage reply = PIDMessage.newBuilder() .setPid(newPid) @@ -101,7 +103,7 @@ class ShellServerService extends ShellServerGrpc.ShellServerImplBase { public void killJob(PIDMessage request, StreamObserver responder) { - int status = manager.getProcessStatus(request.getPid()); + int status = manager.killProcess(request.getPid()); StatusMessage reply = StatusMessage.newBuilder() .setProcessStatus(status) diff --git a/src/main/proto/jobserv.proto b/src/main/proto/jobserv.proto index 351710d..9f1812b 100644 --- a/src/main/proto/jobserv.proto +++ b/src/main/proto/jobserv.proto @@ -10,7 +10,7 @@ package JobServ; service ShellServer { rpc getStatus (PIDMessage) returns (StatusMessage) {} rpc getReturn (PIDMessage) returns (ReturnMessage) {} - rpc getOutput (PIDMessage) returns (OutputMessage) {} + rpc getOutput (OutputRequestMessage) returns (OutputMessage) {} rpc killJob (PIDMessage) returns (StatusMessage) {} rpc newJob (NewJobMessage) returns (PIDMessage) {} } @@ -23,6 +23,11 @@ message ReturnMessage { int32 ProcessReturnCode = 1; } +message OutputRequestMessage { + int32 Pid = 1; + int32 Lines = 2; +} + message OutputMessage { string Output = 1; } diff --git a/src/test/java/JobServ/ProcessManagerTest.java b/src/test/java/JobServ/ProcessManagerTest.java index c0bc851..9071146 100644 --- a/src/test/java/JobServ/ProcessManagerTest.java +++ b/src/test/java/JobServ/ProcessManagerTest.java @@ -145,7 +145,7 @@ public class ProcessManagerTest { // } - String out = manager.getProcessOutput(pid); + String out = manager.getProcessOutput(pid, 2); assertEquals("test\n", out); // calls string.equals() manager.shutdown(); @@ -159,7 +159,7 @@ public class ProcessManagerTest { */ @Test public void getUnknownOutputTest() { - String out = manager.getProcessOutput(532); + String out = manager.getProcessOutput(532, 10); assertEquals("[-] SERVER: Process not found", out); manager.shutdown(); }