I am having a strange issue when trying to execute a block of code (more particularly the ProcessBuilder class in Java)
Code that works:
package modules.user.verify;
import java.io.*;
import java.util.*;
import java.net.*;
public class VerifyUser {
public static void main(String[] args) {
boolean listening = true;
try {
ServerSocket server = new ServerSocket(20002);
while(listening) {
Socket client = server.accept();
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String input, store = "", request = "";
// For all input received, write it to the request buffer.
while((input = in.readLine()) != null) {
request += input;
} // end while loop
BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml"));
while((input = reader.readLine()) != null) {
store += input;
} // end while loop
String acl2 = "(include-book \"modules/user/verify/verify-user\")" +
"(in-package \"ACL2\")" +
"(set-state-ok t)" +
"(set-guard-checking :none)" +
"(testUser \"" + request + "\" \"" + store + "\" state)";
System.out.println("Executing ACL2 runtime...");
ProcessBuilder processBuilder = new ProcessBuilder("acl2");
File log = new File("logs/user/verify/acl2_log.txt");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = processBuilder.start();
PrintWriter procIn = new PrintWriter(process.getOutputStream());
// Write the ACL2 to the process, exit ACL2 and close the socket
procIn.println(acl2);
procIn.println("(good-bye)");
procIn.flush();
procIn.close();
out.close();
in.close();
client.close();
} // end while loop
server.close();
System.exit(0);
} catch(Exception e) {
e.printStackTrace();
} // end try/catch
} // end function main
} // end class VerifyUser
Code that doesn't work:
package modules.user.register;
import java.io.*;
import java.util.*;
import java.net.*;
public class RegisterUser {
public static void main(String[] args) {
boolean listening = true;
try {
// Acquire the listening port for connection to client.
ServerSocket server = new ServerSocket(20001);
while(listening) {
// Wait until the client connects
Socket client = server.accept();
// Handles for input and output streams relating to the socket connection
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
// Buffers
String input, store="", request="";
// Read the input from the connection
while((input = in.readLine()) != null) {
request += input;
} // end while
// Read the contents of the address-book currently stored
BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml"));
while((input = reader.readLine()) != null) {
store += input;
} // end while
// The ACL2 code to execute.
String acl2 = "(include-book \"register-user\")" +
"(in-package \"ACL2\")" +
"(registerUser \"" + request + "\" \"" + store + "\" state)";
// Initialize ACL2 and dump its output to the log
System.out.println("Executing ACL2 runtime for RegisterUser...");
ProcessBuilder processBuilder = new ProcessBuilder("acl2");
File log = new File("logs/user/register/acl2_log.txt");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = processBuilder.start();
PrintWriter procIn = new PrintWriter(process.getOutputStream());
// Write the ACL2 to the process, close ACL2
//procIn.println(acl2);
//procIn.println("(good-bye)");
//procIn.flush();
//procIn.close();
// Old store is old address-book file and new store is newly generated
File oldStore = new File("store/address-book/address-book.xml");
File newStore = new File("store/address-book/temp_address-book.xml");
// Response header information
String response = "<?xml version='1.0'?>" +
"<!DOCTYPE response SYSTEM 'dtd/reponse.dtd'>" +
"<response>";
// Determine if there was a change.
// If entry was added, the length > that old length.
if(oldStore.length() < newStore.length()) {
// Replace old file with new file
oldStore.delete();
newStore.renameTo(oldStore);
// Extract data from request XML
String name = request.substring(request.indexOf("<name>")+6, request.indexOf("</name>")-7);
String domain = request.substring(request.indexOf("<domain>")+8, request.indexOf("</domain>")-9);
// Create the store directory for the user's emails
File storeDirectory = new File("store/email/" + domain + "/" + name + "/");
storeDirectory.mkdirs();
response += "<message>ACCEPT</message>";
} else {
// Remove new file as it is pointless
newStore.delete();
response += "<message>REJECT</message>";
} // end if-else
response += "</response>";
// Writeback the response to the client
out.print(response);
out.flush();
// Close all streams
out.close();
in.close();
client.close();
} // end while
} catch(Exception e) {
e.printStackTrace();
} // end try/catch
} // end function main
} // end class RegisterUser
As you can see, I am not passing any arguments the the program. when I echo %PATH% on my windows DOS shell, it shows that C:\ACL2 is in my ENV vars (which is the folder acl2.exe is located). I've tried changing the acl2 to C:\ACL2\acl2.exe only to have the same results.
What is boggling me is why the first one works perfect and the second one (with almost the same exact code - same exact ProcessBuilder code) does not work.
It appears this block of code is where my problem is:
System.out.println("Executing ACL2 runtime...");
ProcessBuilder processBuilder = new ProcessBuilder("acl2");
File log = new File("logs/user/register/acl2_log.txt");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = processBuilder.start();
PrintWriter procIn = new PrintWriter(process.getOutputStream());
The error:
Executing ACL2 runtime for RegisterUser...
java.io.IOException: Cannot run program "acl2": The system cannot find the path specified
at java.lang.ProcessBuilder.start(Unknown Source)
at modules.user.register.RegisterUser.main(RegisterUser.java:74)
Caused by: java.io.IOException: The system cannot find the path specified
at java.lang.ProcessImpl.openForAtomicAppend(Native Method)
at java.lang.ProcessImpl.newFileOutputStream(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 2 more
What is supposed to happen, is that the Process that gets started is the ACL2 environment, code is sent to it which is executed and then the process is killed (via the (good-bye) command in ACL2). After that the code should exit after a little bit of Java, which is not related to the ACL2 process where the error occurs.
The VerifyUser program invokes ACL2, writes a response to a "server-response.xml" file and exits gracefully without incident.
The RegisterUser program should invoke ACL2, write a response and exit gracefully, and a little java code creates a directory for a user and deletes a store file and renames the newly generated one for user registration.
Since the exception is thrown at
at java.lang.ProcessImpl.openForAtomicAppend(Native Method)
AND you use two different paths:
File log = new File("logs/user/verify/acl2_log.txt");
File log = new File("logs/user/register/acl2_log.txt");
it might be possible, that the acl command is found but that the redirection cannot be performed. In this case the error message is not quite helpful but - if you read between the lines - also not wrong.
Related
I have a VB script to which I need to pass username and password.
I want to run this VB script through Java code programmatically.
Is there a way that I can pass the Windows credentials to the VB script in Java programmatically?
You can have the credentials on the OS environment and read them from there:
String credentials = System.getenv().get("encrypted_credentials_or_something");
And then run your command from Java. However, Runtime.exec() won't work in some cases:
When the command is not on the System's PATH
When arguments are involved
When you want to have access to the process output
When you need to be able to kill the process
When you need to check if it terminated successfully or in error (status code != 0 - which is why you write System.exit(int) to terminate a Java application. The System.exit(1), for example, indicates abnormal termination)
That's why I created this utility class to execute external processes with arguments and everything. It works very well for me:
import java.io.*;
import java.util.*;
public class ExternalCommandHelper {
public static final void executeProcess(File directory, String command) throws Exception {
InputStreamReader in = null;
try {
//creates a ProcessBuilder with the command and its arguments
ProcessBuilder builder = new ProcessBuilder(extractCommandWithArguments(command));
//errors will be printed to the standard output
builder.redirectErrorStream(true);
//directory from where the command will be executed
builder.directory(directory);
//starts the process
Process pid = builder.start();
//gets the process output so you can print it if you want
in = new InputStreamReader(pid.getInputStream());
//simply prints the output while the process is being executed
BufferedReader reader = new BufferedReader(in);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int status = 0;
//waits for the process to finish. Expects status 0 no error. Throws exception if the status code is anything but 0.
if ((status = pid.waitFor()) != 0) {
throw new IllegalStateException("Error executing " + command + " in " + directory.getAbsolutePath() + ". Error code: " + status);
}
} finally {
if (in != null) {
in.close();
}
}
}
//Splits the command and arguments. A bit more reliable than using String.split()
private static String[] extractCommandWithArguments(String command) {
StringTokenizer st = new StringTokenizer(command);
String[] cmdWithArgs = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdWithArgs[i] = st.nextToken();
}
return cmdWithArgs;
}
}
I'm executing a system command on server which gives continuous output till it gets completed. Since it takes a long time to get completed, I want to sent the output from this system command to client in continuous fashion. Any suggestions on how should I do it.
Here is my snippet of code which executes the system command and has the input stream to read from.
I'm invoking this code form my servlet doPost.
Process process = pb.start();
final InputStream is = process.getInputStream();
final StringBuffer strBuff = new StringBuffer();
Thread inputStreamThread = new Thread(){
public void run() {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
while((line = br.readLine()) != null) {
strBuff.append(line + "\n");
}
} catch (IOException e) {
logger.error("IO Exception occured in inputStreamThread=> "+e);
}
}
};
inputStreamThread.start();
inputStreamThread.join();
int exitVal = process.waitFor();
I'm currently working on a project where a client receives shell/console commands from a server, and must execute them.
How do I get Java to run these commands from within either a shell or a command prompt? I'm hoping to be able to disregard the platform type - and not have to specify shell or command prompt - but if I can't, then that's okay.
I must be able to send a sequence of related commands, not just one command. This means that the shell/prompt cannot exit or close between commands.
My current code, as follows, allows for the execution of a sequence of programs, but these commands must somehow be piped into a shell/command prompt, from which the output must be read.
ArrayList<String> comDat = new ArrayList<>();
while(true) {
String input = con.recv();
System.out.println("> " + input);
if(!input.equals("EOF")) comDat.add(input); else {
String[] s = new String[comDat.size()];
for(int i = 0; i < comDat.size(); i++) s[i] = comDat.get(i);
System.out.println("---Command sequence executing---");
Process p = Runtime.getRuntime().exec(s);
p.waitFor();
System.out.println("---ErrorStream output---"); String line = "";
BufferedReader errStream = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while((line = errStream.readLine()) != null) System.out.println("< " + line);
System.out.println("\n---OutputStream output---"); line = "";
BufferedReader outStream = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((line = errStream.readLine()) != null) System.out.println("< " + line);
}
Thread.sleep(200);
}
Thanks for the help!
The basic premise revoles around the fact the dir isn't an external command but is function of cmd.
I would avoid BufferedReaders when reading the output of a process as not all processes use new lines when sending output (such as progress indicators), instead you should read char for char (IMHO).
You should us ProcessBuilder instead of Runtime#exec. It provides better management and allows you to redirect the error stream into the input stream, making it easier to read the input.
import java.io.IOException;
import java.io.InputStream;
public class TestProcessBuilder {
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir");
pb.redirectError();
Process p = pb.start();
InputStreamConsumer isc = new InputStreamConsumer(p.getInputStream());
isc.start();
int exitCode = p.waitFor();
isc.join();
System.out.println("Process terminated with " + exitCode);
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
public static class InputStreamConsumer extends Thread {
private InputStream is;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
int value = -1;
while ((value = is.read()) != -1) {
System.out.print((char)value);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
I am trying to send a file from server side to client side upon request. The file that is sent is encrypted and the client shpuld decrypt it. the encryption process works fine but while decrypting i need to have the DerIOBuffer objetc which I have using serializing. what should i do..please help
server:
import java.net.*;
import java.io.*;
import java.math.BigInteger;
import com.dragongate_technologies.borZoi.*;
public class FileServer {
static final int LISTENING_PORT = 3210;
public static void main(String[] args) {
File directory; // The directory from which the gets the files that it serves.
ServerSocket listener; // Listens for connection requests.
Socket connection; // A socket for communicating with a client.
/* Check that there is a command-line argument.
If not, print a usage message and end. */
if (args.length == 0) {
System.out.println("Usage: java FileServer <directory>");
return;
}
/* Get the directory name from the command line, and make
it into a file object. Check that the file exists and
is in fact a directory. */
directory = new File(args[0]);
if ( ! directory.exists() ) {
System.out.println("Specified directory does not exist.");
return;
}
if (! directory.isDirectory() ) {
System.out.println("The specified file is not a directory.");
return;
}
/* Listen for connection requests from clients. For
each connection, create a separate Thread of type
ConnectionHandler to process it. The ConnectionHandler
class is defined below. The server runs until the
program is terminated, for example by a CONTROL-C. */
try {
listener = new ServerSocket(LISTENING_PORT);
System.out.println("Listening on port " + LISTENING_PORT);
while (true) {
connection = listener.accept();
new ConnectionHandler(directory,connection);
}
}
catch (Exception e) {
System.out.println("Server shut down unexpectedly.");
System.out.println("Error: " + e);
return;
}
} // end main()
static class ConnectionHandler extends Thread {
// An object of this class is a thread that will
// process the connection with one client. The
// thread starts itself in the constructor.
File directory; // The directory from which files are served
Socket connection; // A connection to the client.
TextReader incoming; // For reading data from the client.
PrintWriter outgoing; // For transmitting data to the client.
ConnectionHandler(File dir, Socket conn) {
// Constructor. Record the connection and
// the directory and start the thread running.
directory = dir;
connection = conn;
start();
}
void sendIndex() throws Exception {
// This is called by the run() method in response
// to an "index" command. Send the list of files
// in the directory.
String[] fileList = directory.list();
for (int i = 0; i < fileList.length; i++)
outgoing.println(fileList[i]);
outgoing.flush();
outgoing.close();
if (outgoing.checkError())
throw new Exception("Error while transmitting data.");
}
void ecies_ex(String fileName) throws Exception {
// This function encrypts the file that has been requested
// by the client.
String at1,dc1,der1;
OutputStream os = connection.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
ECDomainParameters dp = ECDomainParameters.NIST_B_163();
ECPrivKey skA = new ECPrivKey(dp, BigInteger.valueOf(123));
ECPubKey pkA = new ECPubKey(skA);
ECPrivKey skB = new ECPrivKey(dp, BigInteger.valueOf(230));
ECPubKey pkB = new ECPubKey(skB);
File file = new File(directory,fileName);
if ( (! file.exists()) || file.isDirectory()) {
// (Note: Don't try to send a directory, which
// shouldn't be there anyway.)
outgoing.println("error");
}
else {
outgoing.println("ok");
String pt1 = new String();
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(fileName));
while ((sCurrentLine = br.readLine()) != null) {
pt1=pt1+"\n"+sCurrentLine;
}
} catch (IOException e) {
e.printStackTrace();
}
ECIES crypt = new ECIES(skA, pkB, pt1.getBytes()); // encrypt the data
try {
DerIOBuffer der = new DerIOBuffer(crypt);
oos.writeObject(der);
ECIES decrypt = der.toECIES();
dc1=decrypt.toString2(); //cipher text
//at1=decrypt.toString3(); //authentication tag
FileWriter fstream = new FileWriter("encrypted.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write(dc1);
//Close the output stream
out.close();
} catch (Exception e) {
System.out.println(e.toString());
}
TextReader fileIn = new TextReader( new FileReader("encrypted.txt") );
while (fileIn.peek() != '\0') {
// Read and send lines from the file until
// an end-of-file is encountered.
String line = fileIn.getln();
outgoing.println(line);
}
}
outgoing.flush();
// oos.close();
// os.close();
outgoing.close();
if (outgoing.checkError())
throw new Exception("Error while transmitting data.");
}
public void run() {
// This is the method that is executed by the thread.
// It creates streams for communicating with the client,
// reads a command from the client, and carries out that
// command. The connection is logged to standard output.
// An output beginning with ERROR indicates that a network
// error occurred. A line beginning with OK means that
// there was no network error, but does not imply that the
// command from the client was a legal command.
String command = "Command not read";
try {
incoming = new TextReader( connection.getInputStream() );
outgoing = new PrintWriter( connection.getOutputStream() );
command = incoming.getln();
if (command.equals("index")) {
sendIndex();
}
else if (command.startsWith("get")){
String fileName = command.substring(3).trim();
ecies_ex(fileName);
//sendFile(fileName);
}
else {
outgoing.println("unknown command");
outgoing.flush();
}
System.out.println("OK " + connection.getInetAddress()
+ " " + command);
}
catch (Exception e) {
System.out.println("ERROR " + connection.getInetAddress()
+ " " + command + " " + e);
}
finally {
try {
connection.close();
}
catch (IOException e) {
}
}
}
} // end nested class ConnectionHandler
} //end class FileServer
client :
import java.net.*;
import java.io.*;
import java.math.BigInteger;
import com.dragongate_technologies.borZoi.*;
public class FileClient {
static final int LISTENING_PORT = 3210;
public static void main(String[] args) {
String computer; // Name or IP address of server.
Socket connection; // A socket for communicating with that computer.
PrintWriter outgoing; // Stream for sending a command to the server.
TextReader incoming; // Stream for reading data from the connection.
String command; // Command to send to the server.
String pt3;
ECDomainParameters dp = ECDomainParameters.NIST_B_163();
ECPrivKey skB = new ECPrivKey(dp, BigInteger.valueOf(230));
//ECPrivKey skB = new ECPrivKey (dp);
ECPubKey pkB = new ECPubKey(skB);
/* Check that the number of command-line arguments is legal.
If not, print a usage message and end. */
if (args.length == 0 || args.length > 3) {
System.out.println("Usage: java FileClient <server>");
System.out.println(" or java FileClient <server> <file>");
System.out.println(" or java FileClient <server> <file> <local-file>");
return;
}
/* Get the server name and the message to send to the server. */
computer = args[0];
if (args.length == 1)
command = "index";
else
command = "get " + args[1];
/* Make the connection and open streams for communication.
Send the command to the server. If something fails
during this process, print an error message and end. */
try {
connection = new Socket( computer, LISTENING_PORT );
incoming = new TextReader( connection.getInputStream() );
outgoing = new PrintWriter( connection.getOutputStream() );
outgoing.println(command);
outgoing.flush();
}
catch (Exception e) {
System.out.println(
"Can't make connection to server at \"" + args[0] + "\".");
System.out.println("Error: " + e);
return;
}
/* Read and process the server's response to the command. */
try {
if (args.length == 1) {
// The command was "index". Read and display lines
// from the server until the end-of-stream is reached.
System.out.println("File list from server:");
while (incoming.eof() == false) {
String line = incoming.getln();
System.out.println(" " + line);
}
}
else {
// The command was "get <file-name>". Read the server's
// response message. If the message is "ok", get the file.
String message = incoming.getln();
if (! message.equals("ok")) {
System.out.println("File not found on server.");
return;
}
PrintWriter fileOut; // For writing the received data to a file.
if (args.length == 3) {
// Use the third parameter as a file name.
fileOut = new PrintWriter( new FileWriter(args[2]) );
}
else {
// Use the second parameter as a file name,
// but don't replace an existing file.
File file = new File(args[1]);
if (file.exists()) {
System.out.println("A file with that name already exists.");
System.out.println("To replace it, use the three-argument");
System.out.println("version of the command.");
return;
}
fileOut = new PrintWriter( new FileWriter(args[1]) );
}
while (incoming.peek() != '\0') {
// Copy lines from incoming to the file until
// the end of the incoming stream is encountered.
String line = incoming.getln();
fileOut.println(line);
}
InputStream is = connection.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
DerIOBuffer der = (DerIOBuffer)ois.readObject();
ECIES decrypt = der.toECIES();
byte[] pt2 = decrypt.decrypt(skB); // decrypt the data
pt3=new String(pt2);
if (fileOut.checkError()) {
System.out.println("Some error occurred while writing the file.");
System.out.println("Output file might be empty or incomplete.");
}
}
}
catch (Exception e) {
System.out.println("Sorry, an error occurred while reading data from the server.");
System.out.println("Error: " + e);
}
} // end main()
} //end class FileClient
If you care about errors, you should not use PrintWriter. Why? Because if an error does occur on output via a PrintWriter, you have no way to find out what it was. This is what makes it difficult to figure out what the real problem is in this case. I recommend that you fix this so that you can get to the real cause of the problem.
The real problem could be related to to the following issues:
If the stuff you are trying to write could be binary, you shouldn't use PrintWriter ... or Readers / Writers at all.
You seem to be using Object serialization unnecessarily ... and on a class that looks like it may not be serializable.
Based on the difficulty I had in finding documentation for the "borZoi" library ... and other things ... I think you may have made a poor choice of library for doing crypto work.
I want to run a C/C++ program's exe file using java.......and handle its input and output......
my code is
import java.io.*;
class run2 {
public static void main(String[] args) throws java.io.IOException {
String[] command = new String[3];
command[0] = "cmd";
command[1] = "/C";
// command[2] = "java Run1";
command[2] = "start C:\\WE.EXE";
Process p = Runtime.getRuntime().exec(command);
String i = "20";
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
p.getInputStream()));
BufferedWriter st = new BufferedWriter(new OutputStreamWriter(
p.getOutputStream()));
String s = null;
System.out.println("Here is the standard output of the command:\n");
s = stdInput.readLine();
System.out.println(s);
st.write(i);
st.newLine();
st.flush();
while ((s = stdInput.readLine()) != null) {
System.out.println("Stdout: " + s);
}
try {
System.out.println("Exit status = " + p.waitFor());
}
catch (InterruptedException e) {
}
stdInput.close();
}
}
i am getting an error which says pipes is closed
do help me out.....
Well, first of all, if there isn't a WE.EXE in C:/, that could be an issue. If no process is ever launched, of course you can't do anything with its input/output pipes.
However, presuming you have a WE.EXE, your error is probably at:
st.flush();
Your application is opening up WE.EXE in command prompt, or cmd.exe, who will take care of both standard input and standard output. Your call stdInput.readLine(); will wait until WE.EXE, and therefore cmd.exe, terminates, at which point the output stream will be closed (and you obviously can't write onto a closed pipe).
So if you want to handle input and output yourself, you should launch WE.exe directly, like:
Process p = Runtime.getRuntime().exec("C://WE.EXE");
Additionally, you may consider using ProcessBuilder instead of Runtime.exec.
Small detail, but consider using Java's naming conventions--for example, your class name would be Run2 (or something more descriptive) instead of run2.
You are trying to read from a stream (stdInput) that does not exist yet.
It won't exist until the WE.EXE program writes something to it.
Just wait until you send the commands to the program.
In other words, take out the first input line, and it will work fine.
//s = stdInput.readLine();
System.out.println(s);
st.write(i);
st.newLine();
st.flush();
while ((s = stdInput.readLine()) != null)
{ System.out.println("Stdout: " + s); }