UX tweaks, better output request behaviour

This commit is contained in:
Aidan Hahn 2019-05-23 23:29:41 -07:00
parent 88e745346e
commit 55b77789c3
No known key found for this signature in database
GPG key ID: 327711E983899316
7 changed files with 62 additions and 43 deletions

View file

@ -54,8 +54,8 @@ public class JobServClient {
try { try {
return Integer.parseInt(this.programArgs[index]); return Integer.parseInt(this.programArgs[index]);
} catch (InputMismatchException e) { } catch (NumberFormatException e) {
System.out.println(this.programArgs[index] + " is not a valid int, much less a valid pid"); System.out.println(this.programArgs[index] + " is not a valid integer");
return -1; return -1;
} }
@ -69,9 +69,9 @@ public class JobServClient {
System.out.println("... new (command)\n"+ System.out.println("... new (command)\n"+
"Starts a new process on the server\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"+ "example: ./client key.pem cert.crt ca.crt localhost 8448 new echo hello world!\n\n"+
"... output (pid)\n"+ "... output (pid) (lines)\n"+
"Garners output from process on server\n"+ "Garners (lines) lines of output from process (pid) on server\n"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 output 0\n\n"+ "example: ./client key.pem cert.crt ca.crt localhost 8448 output 0 5\n\n"+
"... status (pid)\n"+ "... status (pid)\n"+
"Returns whether process on server is running"+ "Returns whether process on server is running"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 status 0\n\n"+ "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 * makes a new process
*/ */
public void makeNewProcess() { public void makeNewProcess() {
if (this.programArgs.length < 6) {
System.out.println("Improper formatting, try client --help");
return;
}
String command = ""; String command = "";
for (int token = 6; token < this.programArgs.length; token++) { for (int token = 6; token < this.programArgs.length; token++) {
command += " " + this.programArgs[token]; command += " " + this.programArgs[token];
@ -121,12 +116,18 @@ public class JobServClient {
* gets output from a process * gets output from a process
*/ */
public void getOutput() { 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 candidatePid = this.getPidArg(6);
int lines = this.getPidArg(7);
if (candidatePid < 0) { if (candidatePid < 0) {
return; return;
} }
String processOutput = this.api.getProcessOutput(candidatePid); String processOutput = this.api.getProcessOutput(candidatePid, lines);
System.out.println(processOutput); System.out.println(processOutput);
} }

View file

@ -63,11 +63,12 @@ class JobServClientAPIConnector {
* sends the server a request for output from the process identified by 'pid' * sends the server a request for output from the process identified by 'pid'
* returns process output as string * returns process output as string
*/ */
public String getProcessOutput(int pid) { public String getProcessOutput(int pid, int lines) {
logger.info("[+] requesting output"); logger.info("[+] requesting output");
PIDMessage request = PIDMessage.newBuilder() OutputRequestMessage request = OutputRequestMessage.newBuilder()
.setPid(pid) .setPid(pid)
.setLines(lines)
.build(); .build();
OutputMessage response; OutputMessage response;

View file

@ -8,10 +8,11 @@
package JobServ; package JobServ;
import java.util.Scanner;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
/* /*
* ProcessController * ProcessController
@ -28,7 +29,8 @@ class ProcessController {
// interactive processes (out of scope for initial API) // interactive processes (out of scope for initial API)
private OutputStream output; private OutputStream output;
private InputStream input; private InputStream input;
private Scanner outputScanner; private InputStreamReader inputIntermediateStream;
private BufferedReader reader;
private Process process; private Process process;
@ -46,8 +48,8 @@ class ProcessController {
this.process = Runtime.getRuntime().exec(command); this.process = Runtime.getRuntime().exec(command);
this.output = this.process.getOutputStream(); this.output = this.process.getOutputStream();
this.input = this.process.getInputStream(); this.input = this.process.getInputStream();
this.outputScanner = new Scanner(this.input); this.inputIntermediateStream = new InputStreamReader(this.input);
this.outputScanner.useDelimiter("\\A"); this.reader = new BufferedReader(this.inputIntermediateStream);
} }
/* /*
@ -61,9 +63,6 @@ class ProcessController {
/* /*
* getStatus() * getStatus()
* returns whether or not the process is running * 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 * TODO: (for future release) return thread state
*/ */
@ -85,7 +84,7 @@ class ProcessController {
* returns the exit code of the process * returns the exit code of the process
* 256 if process is still running * 256 if process is still running
* 257 if process was killed manually and no longer exists * 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() { public int getReturn() {
if (this.killedManually) { if (this.killedManually) {
@ -103,17 +102,23 @@ class ProcessController {
* getOutput() * getOutput()
* gets output from process * gets output from process
*/ */
public String getOutput() { public String getOutput(int lines) {
if (this.killedManually) { String output = "";
return ""; 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 * Cleans up resources and destroys process
*/ */
public void kill() { public void kill() {
if (this.killedManually) {
System.err.println("[~] Tried to kill already killed process");
return;
}
try { try {
this.input.close(); this.input.close();
this.output.close(); this.output.close();
this.outputScanner.close(); this.inputIntermediateStream.close();
this.reader.close();
this.process.destroy(); this.process.destroy();
} catch (IOException e) {
// streams already closed
}
this.killedManually = true; this.killedManually = true;
} catch (IOException e) {
System.err.println("[-] Killing process failed: " + e.getMessage());
}
} }
} }

View file

@ -140,7 +140,7 @@ class ProcessManager {
* returns output of process 'pid' * returns output of process 'pid'
* or returns description of error * or returns description of error
*/ */
public String getProcessOutput(int pid) { public String getProcessOutput(int pid, int lines) {
try { try {
if(!this.getLock(pid)) { if(!this.getLock(pid)) {
return "[-] SERVER: Process not found"; return "[-] SERVER: Process not found";
@ -152,7 +152,7 @@ class ProcessManager {
} }
ProcessController candidate = this.processMap.get(pid); ProcessController candidate = this.processMap.get(pid);
String output = candidate.getOutput(); String output = candidate.getOutput(lines);
this.releaseLock(pid); this.releaseLock(pid);
return output; return output;
} }

View file

@ -47,10 +47,11 @@ class ShellServerService extends ShellServerGrpc.ShellServerImplBase {
* implements api endpoint as defined in jobserv.proto * implements api endpoint as defined in jobserv.proto
*/ */
@Override @Override
public void getOutput(PIDMessage request, public void getOutput(OutputRequestMessage request,
StreamObserver<OutputMessage> responder) { StreamObserver<OutputMessage> responder) {
String output = manager.getProcessOutput(request.getPid()); String output = manager.getProcessOutput(request.getPid(),
request.getLines());
OutputMessage reply = OutputMessage.newBuilder() OutputMessage reply = OutputMessage.newBuilder()
.setOutput(output) .setOutput(output)
@ -67,7 +68,8 @@ class ShellServerService extends ShellServerGrpc.ShellServerImplBase {
public void newJob(NewJobMessage request, public void newJob(NewJobMessage request,
StreamObserver<PIDMessage> responder) { StreamObserver<PIDMessage> responder) {
int newPid = manager.newProcess(request.getCommand()); String command = request.getCommand();
int newPid = manager.newProcess(command);
PIDMessage reply = PIDMessage.newBuilder() PIDMessage reply = PIDMessage.newBuilder()
.setPid(newPid) .setPid(newPid)
@ -101,7 +103,7 @@ class ShellServerService extends ShellServerGrpc.ShellServerImplBase {
public void killJob(PIDMessage request, public void killJob(PIDMessage request,
StreamObserver<StatusMessage> responder) { StreamObserver<StatusMessage> responder) {
int status = manager.getProcessStatus(request.getPid()); int status = manager.killProcess(request.getPid());
StatusMessage reply = StatusMessage.newBuilder() StatusMessage reply = StatusMessage.newBuilder()
.setProcessStatus(status) .setProcessStatus(status)

View file

@ -10,7 +10,7 @@ package JobServ;
service ShellServer { service ShellServer {
rpc getStatus (PIDMessage) returns (StatusMessage) {} rpc getStatus (PIDMessage) returns (StatusMessage) {}
rpc getReturn (PIDMessage) returns (ReturnMessage) {} rpc getReturn (PIDMessage) returns (ReturnMessage) {}
rpc getOutput (PIDMessage) returns (OutputMessage) {} rpc getOutput (OutputRequestMessage) returns (OutputMessage) {}
rpc killJob (PIDMessage) returns (StatusMessage) {} rpc killJob (PIDMessage) returns (StatusMessage) {}
rpc newJob (NewJobMessage) returns (PIDMessage) {} rpc newJob (NewJobMessage) returns (PIDMessage) {}
} }
@ -23,6 +23,11 @@ message ReturnMessage {
int32 ProcessReturnCode = 1; int32 ProcessReturnCode = 1;
} }
message OutputRequestMessage {
int32 Pid = 1;
int32 Lines = 2;
}
message OutputMessage { message OutputMessage {
string Output = 1; string Output = 1;
} }

View file

@ -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() assertEquals("test\n", out); // calls string.equals()
manager.shutdown(); manager.shutdown();
@ -159,7 +159,7 @@ public class ProcessManagerTest {
*/ */
@Test @Test
public void getUnknownOutputTest() { public void getUnknownOutputTest() {
String out = manager.getProcessOutput(532); String out = manager.getProcessOutput(532, 10);
assertEquals("[-] SERVER: Process not found", out); assertEquals("[-] SERVER: Process not found", out);
manager.shutdown(); manager.shutdown();
} }