I want to run the following command from a java program:
socat -x -u /dev/ttyFTDI0,raw,echo=0,crnl /dev/ttyFTDI1,raw,echo=0,crnl
This program is supposed to run for an indefinite time while outputting hex strings like this:
b4 03 03 92 00 01 3f c6 b4 03 10 03 00 01 6a af
My current testing code is:
public void testOutput() {
try {
List<String> command = new ArrayList<String>();
command.add("socat");
command.add("-x");
command.add("-u");
command.add("/dev/ttyFTDI0,raw,echo=0,crnl");
command.add("/dev/ttyFTDI1,raw,echo=0,crnl");
ProcessBuilder proBui = new ProcessBuilder(command);
Process process = proBui.start();
//process.waitFor();
BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (true) {
String temp = r.readLine();
if (temp != null && !temp.isEmpty()) {
//do something with data
System.out.print(temp);
}
Thread.sleep(1);
}
} catch (Exception ex) {
System.out.println(ex);
}
}
While this code works for commands that finish after a given time, commands like the one given or watch ls won't work.
According to the socat documentation, the -x option
Writes the transferred data not only to their target streams, but also to stderr.
You are reading from process.getInputStream() which is connected to the native process stdout - to get stderr you should read process.getErrorStream() instead.
Related
I have a java program it does execute the shell command then wait for command to exit from shell to get result. But Process unable to read the output from command it just print result empty.
However same command if I run from shell prompt I could see result printing there..
{
[root#localhost home]# tsp -I marker input.mpg -P marker -a 10 -v 10 -O file output.mpg
marker: 10
marker: 20
marker: 30
marker: 40
marker: 50
marker: 60
marker: 70
marker: 80
marker: 90
marker: 100
marker: OK
[root#localhost home]#
}
Java program to execute shell command here
{
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String command = "tsp -I olesmarker input.mpg -P " + "olesmarker -a 10 -v 10 -O file output.mpg";
String output = obj.executeCommand(command);
System.out.println("Command Result = " + output);
}
private String executeCommand(String command) {
StringBuilder output = new StringBuilder();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
Are you sure that your "tsp" program is generating these "marker" progress messages to standard out? Some programs are using the shell standard err channel. Especially programs doing conversions (the '-O file output.mpg' kind of indicates such a functionality) often use the shell-std.out as default output for conversion result and the shell-sdt.err for status and progress messages. (very useful for connecting commands with pipes on the shell).
I would suggest to try
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
instead of
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
Hope this helps..
I am sending multiple commands in a byte array format and receive responses based on the commands that were sent in a typical client/server communication. My Java app is the client running on Windows 7 and I know what commands to send and what I am expected to receive in the response. However, I do not have any control or have any knowledge of the server source code.
The problem I am having is that on the second command I sent or any commands after that, the first byte of the array is being dropped. When I send the first command, I get the proper response since the first byte is not dropped. When sending the next command or any commands after that, the first byte is dropped which the server does not respond since the command is not in the proper format for the server to recognize.
I am sending these commands over a Java SSLSocket DataOutputStream and of course I am receiving the responses on a DataInputStream. I first perform a handshake with the server and proceed on after the handshake is successful. At this point is when I send the first command and receive the response shown here in hex.:
Sending: 01 03 03
Receive: 01 0e fd 85 02 09 01 01 04 01 06
The next command being sent:
Sending: 01 48 65 6c 6c 6f
But this is where I do not receive a response from the server.
When printing out the javax.net.debug output, I can see that the first byte '01' does drop or went missing somehow.
Padded plaintext before ENCRYPTION: len = 32
0000: 48 65 6C 6C 6F FE 57 F9 4A 29 13 8F 2B AB 71 A3 Hello.W.J)..+.q.
0010: 16 12 29 FF D5 DE 12 48 8B 06 06 06 06 06 06 06 ..)....H........
main, WRITE: TLSv1 Application Data, length = 32
[Raw write]: length = 37
0000: 17 03 01 00 20 34 42 ED 88 FC 41 2D 13 1A FD BA .... 4B...A-....
0010: 64 0E 9D C7 FE 11 76 96 48 09 A6 BC B2 BC 0E FA d.....v.H.......
0020: C8 5B 79 4B 82 .[yK.
The following is my source code:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.TrustManager;
import java.security.KeyStore;
public class SSLSocketTest
{
private SSLSocket sslSocket = null;
private SSLSocketFactory sslSocketFactory = null;
private String ipAddress = "192.168.100.99";
private int port = 9999;
DataOutputStream dataOS = null;
DataInputStream dataIS = null;
private boolean handshakeSuccessful = false;
public static void main(String[] args)
{
SSLSocketTest sslSocketTest = new SSLSocketTest();
sslSocketTest.sslSocketConnect();
}
SSLSocketTest()
{
System.setProperty("javax.net.debug", "all");
try{
File certFile = new File("cacerts");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
char[] certPassword = "changeit".toCharArray();
InputStream fileIS = new FileInputStream(certFile);
keyStore.load(fileIS, certPassword);
fileIS.close();
SSLContext sslContext = SSLContext.getInstance("TLSv1");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
X509TrustManager defaultTrustManager = (X509TrustManager)trustManagerFactory.getTrustManagers()[0];
sslContext.init(null, new TrustManager[] {defaultTrustManager}, null);
sslSocketFactory = sslContext.getSocketFactory();
}catch(Exception e){
e.printStackTrace();
}
}
public void sslSocketConnect()
{
try{
sslSocket = (SSLSocket) sslSocketFactory.createSocket(ipAddress, port);
dataOS = new DataOutputStream(sslSocket.getOutputStream());
dataIS = new DataInputStream(sslSocket.getInputStream());
sslSocket.setSoTimeout(15000);
//Handshake
sslSocket.addHandshakeCompletedListener(new MyHandshakeListener());
sslSocket.startHandshake();
while(!handshakeSuccessful)
{
Thread.sleep(100);
}
//Sending commands
byte[] firstCommand = new byte[]{(byte)0x01, (byte)0x03, (byte)0x03};
String[] firstCommandResponse = processCommand(firstCommand);
byte[] secondCommand = new byte[]{(byte)0x01, (byte)0x48, (byte)0x65, (byte)0x6C, (byte)0x6C, (byte)0x6F};
String[] secondCommandResponse = processCommand(secondCommand);
disconnect();
}catch(Exception e){
e.printStackTrace();
}
}
public void disconnect()
{
try{
byte[] endConnection = new byte[]{(byte)0x01, (byte)0x01, (byte)0x02, (byte)0x03};
processCommand(endConnection);
dataOS.close();
dataIS.close();
sslSocket.close();
}catch (Exception e){
e.printStackTrace();
}
}
public String[] processCommand(byte[] command)
{
String[] returnResponse = null;
byte[] commandResponse = new byte[120];
byte[] trimCommandResponse;
try{
int commandResponseLength = -1;
int errorCount = 0;
while(commandResponseLength == -1)
{
StringBuilder cmdStr = new StringBuilder();
cmdStr.append("Sending: ");
for(int i=0; i<command.length; i++)
{
cmdStr.append(fixHexStringData(Integer.toHexString(command[i])) + " ");
}
System.out.println(cmdStr.toString());
dataOS.write(command, 0, command.length);
dataOS.flush();
commandResponseLength = dataIS.read(commandResponse);
errorCount++;
if(errorCount == 3)
{
throw new Exception();
}
}
returnResponse = new String[commandResponseLength];
trimCommandResponse = new byte[commandResponseLength];
//Getting Reponse Data
for(int i=0; i<commandResponseLength; i++)
{
returnResponse[i] = fixHexStringData(Integer.toHexString(commandResponse[i]));
trimCommandResponse[i] = commandResponse[i];
}
StringBuilder rcvStr = new StringBuilder();
rcvStr.append("Receive: ");
for(int i=0; i<returnResponse.length; i++)
{
rcvStr.append(returnResponse[i] + " ");
}
System.out.println(rcvStr.toString());
}catch(Exception e){
e.printStackTrace();
}
return returnResponse;
}
private String fixHexStringData(String dataByte)
{
if(dataByte.length() < 2)
{
dataByte = "0" + dataByte;
}
else if(dataByte.length() > 2)
{
dataByte = dataByte.substring(dataByte.length()-2);
}
return dataByte;
}
class MyHandshakeListener implements HandshakeCompletedListener
{
public void handshakeCompleted(HandshakeCompletedEvent e)
{
System.out.println("Handshake succesful!");
handshakeSuccessful = true;
}
}
}
The questions I have are:
Am I missing a step in writing out the byte array? I have done this over a standard Java Socket with no issues, so is writing over a SSL Socket different from a standard Socket? I looked for this but did not see anything different.
Could this be a certificate issue? If the handshake and the first command are successful, would this mean that the communication has been established at this point and it is beyond the certificate?
Could the server be affecting this? If so, what could be the reason behind this? If writing the byte array to the DataOutputStream is on the client side and the first byte is dropped, how could the server have any affect on the client side?
Could this be a JVM bug?
It looks like this is actually a function of the JSSE implementation which splits the data between two packets. The first byte goes in one packet and the rest in the next. More detail at this answer
You should be able to override this functionality by including
System.setProperty("jsse.enableCBCProtection", "false");
I have a very strange situation. I connect my Java software with a device, let´s call it "Black Box" (because I cannot look into it or make traces within it). I am adressing a specific port (5550) and send commands as byte sequences on a socket. As a result, I get an answer from the Black Box on the same socket.
Both my commands and the replies are prefixed in a pre-defined way (according to the API) and have an XOR checksum.
When I run the code from Windows, all is fine: Command 1 gets its Reply 1 and Command 2 gets its Reply 2.
When I run the code from Android (which is actually my target - Windows came into play to track down the error) it gets STRANGE: Command 1 gets its Reply 1 but Command 2 does not. When I play with Command 2 (change the prefix illegally, violate the checksum) the Black Box reacts as expected (with an error reply). But with the correct Command 2 being issued from Android, the Reply is totally mis-formed: Wrong prefix and missing checksum.
In the try to analyse the error I tried WireShark and this shows that on the network interface, the Black Box is sending the RIGHT Reply 2, but evaluating this reply in Java from the socket, it is wrong. How can this be when all is fine for Command/Reply 1???
Strange is, that parts of the expected data are present:
Expected: ff fe e4 04 00 11 00 f1
Received: fd fd fd 04 00 11 00 // byte 8 missing
I am attaching the minimalistic code to force the problem. What could falsify the bytes which I receive? Is there a "raw" access in Java to the socket which could reveal the problem?
I am totally confused so any help would be appreciated:
String address = "192.168.1.10";
int port = 5550;
Socket socket;
OutputStream out;
BufferedReader in;
try {
socket = new Socket(address, port);
out = socket.getOutputStream();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// This is "Command 1" which is receiving the right reply
// byte[] allesAn = new byte[] {(byte)0xff, (byte)0xfe, (byte)0x21, (byte)0x81, (byte)0xa0};
// out.write(allesAn);
// This is "Command 2" which will not receive a right reply
byte[] getLokInfo3 = new byte[] {(byte)0xff, (byte)0xfe, (byte)0xe3, (byte)0, (byte)0, (byte)3, (byte)0xe0};
out.write(getLokInfo3);
out.flush();
while (true) {
String received = "";
final int BufSize = 1000;
char[] buffer = new char[BufSize];
int charsRead = 0;
charsRead = in.read(buffer, 0, BufSize);
// Convert to hex presentation
for (int i=0; i < charsRead; i++) {
byte b = (byte)buffer[i];
received += hexByte((b + 256) % 256) + " ";
}
String result = charsRead + ">" + received + "<";
Log.e("X", "Read: " + result);
}
} catch (Exception e) {
Log.e("X", e.getMessage() + "");
}
with
private static String hexByte(int value) {
String s = Integer.toHexString(value);
return s.length() % 2 == 0 ? s : "0" + s;
}
Here is what wireshark says, showing the expected 8 bytes:
Below, you see a program that I wrote to see the state of different fields and memory allocations after calling requestObjectDeletion() method:
public class ReqObjDel extends Applet {
static byte[] buffer = new byte[2];
static boolean isNull = false;
private ReqObjDel() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new ReqObjDel().register();
}
public void process(APDU arg0) throws ISOException {
if (selectingApplet()) {
return;
}
if (buffer != null && (short) buffer.length == (short) 10) {
return;
}
byte[] oldBuffer = buffer;
buffer = new byte[10];
JCSystem.requestObjectDeletion();
if (oldBuffer == null)
isNull = true;
if (isNull) {
ISOException.throwIt((short) 0x1111);
} else
ISOException.throwIt((short) 0x0000);
}
}
As far as I know,this method reclaims memory which is being used by “unreachable” objects. To be “unreachable”, an object can neither be pointed to by a static field nor by an object field. So calling requestObjectDeletion() in the above program reclaims the part of EEPROM that oldBuffer is refer to (As far as I know, oldBuffer is neither class field nor object field,right?). In this situation I expect that oldBuffer == null and therefore the JCRE must return 0x1111. But the output is 0x0000 unexpectedly :
OSC: opensc-tool -s 00a404000b0102030405060708090000 -s 00000000
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00
Received (SW1=0x00, SW2=0x00)
Q1 : What can I conclude?
That part of memory is not reclaimed?
That part of memory is reclaimed but oldBuffer is a reference to it still?
something else?
Q2 : Is there any way to obtain the free memory size before and after of calling this method? (i.e. is there any method that return the size of free memory[not allocated]?)
Update 1 : Trying JCSystem.getAvailableMemory()
Based on #vojta answer, I changed my program in a way that the line byte[] oldBuffer = buffer; runs only once (using a flag named isFirstInvocation) and return the free available memory in two consecutive process() method invocation :
public class ReqObjDel extends Applet {
static byte[] buffer = new byte[10];
static boolean isFirstInvocation = true;
private ReqObjDel() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new ReqObjDel().register();
}
public void process(APDU arg0) throws ISOException {
if (selectingApplet()) {
return;
}
short availableMem1 = JCSystem
.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
if (isFirstInvocation) {
byte[] oldBuffer = buffer;
buffer = new byte[10];
JCSystem.requestObjectDeletion();
firstInvocation = false;
}
short availableMem2 = JCSystem
.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
short availableMemory = (short) (availableMem1 + availableMem2);
ISOException.throwIt(availableMemory);
}
}
And this is the output :
OSC: osc -s 00a404000b0102030405060708090000 -s 00000000 -s 00000000
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00
Received (SW1=0xFF, SW2=0xFE)
Sending: 00 00 00 00
Received (SW1=0xFF, SW2=0xFE)
As both invocations return an equal value, I think the JCRE reclaims that part of memory immediately after calling requestObjectDeletion(), right?
First of all, a rule based on my personal experience: if possible, do not use the garbage collector at all. GC is very slow and could be even dangerous (see Javacard - power loss during garbage collection).
Q1:
If you really have to use GC, read the documentation:
This method is invoked by the applet to trigger the object deletion
service of the Java Card runtime environment. If the Java Card runtime
environment implements the object deletion mechanism, the request is
merely logged at this time. The Java Card runtime environment must
schedule the object deletion service prior to the next invocation of
the Applet.process() method.
Shortly speaking, JCSystem.requestObjectDeletion(); has no immediate effect. That is why your local variable oldBuffer remains unchanged.
Q2: To find out how much persistent memory is available to your applet, use:
JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
ANSWER to UPDATE 1: JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT) may be confusing for cards with more than 32767 bytes of persistent memory. Such cards usually offer their own proprietary ways to find out available memory.
If the number of available bytes is greater than 32767, then this
method returns 32767.
I am trying to call cleartool from an java application, but cleartool hangs even for a simple "-version" argument. Running cleardiff instead of cleartool works fine, so apparently there is something specific with the cleartool program (which I assume is related to its interactive capabilities).
The following program
import java.io.*;
import java.util.*;
public class ExecTesting extends Thread {
private List<String> command = new ArrayList<String>();
public ExecTesting (List<String> command) {
super();
this.command = command;
}
private void print(String s) {
System.out.println(s);
}
#Override
public void run() {
Process process;
OutputStream stdin;
InputStream stdout;
InputStream stderr;
String line;
try {
String commandString = joinList(command, " ");
print("Executing: " + commandString);
// runtime.exec has several issues (http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1)
// better to use ProcessBuilder (http://java.sun.com/developer/JDCTechTips/2005/tt0727.html#2)
//process = Runtime.getRuntime().exec(commandString);
process = new ProcessBuilder(command).start();
// it fails in both cases though
stdin = process.getOutputStream();
stdout = process.getInputStream();
stderr = process.getErrorStream();
BufferedReader bufferedStderr = new BufferedReader(new InputStreamReader(stderr));
while ((line = bufferedStderr.readLine()) != null) {
print("stderr: " + line);
}
bufferedStderr.close();
BufferedReader bufferedStdout = new BufferedReader(new InputStreamReader(stdout));
while ((line = bufferedStdout.readLine()) != null) {
print("stdout: " + line);
}
bufferedStdout.close();
stdin.close();
stdout.close();
stderr.close();
process.waitFor();
print("Execution finished, exit code " + process.exitValue());
process.destroy();
} catch (IOException e) {
print("IOException: " +e.getStackTrace());
} catch (InterruptedException e) {
print("InterruptedException: " + e.getStackTrace());
}
}
/* assumes a list with at least one element */
private static String joinList(List<String> list, String glue) {
Iterator<String> i = list.iterator();
String ret = i.next();
while (i.hasNext()) {
ret += glue + i.next();
}
return ret;
}
public static void main(String[] args) {
ArrayList<String> cmd1 = new ArrayList<String>();
cmd1.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe");
cmd1.add("-version");
ExecTesting et1 = new ExecTesting(cmd1);
et1.start();
ArrayList<String> cmd2 = new ArrayList<String>();
//cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe");
cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleartool.exe");
cmd2.add("-version");
ExecTesting et2 = new ExecTesting(cmd2);
et2.start();
et1 = new ExecTesting(cmd1);
et1.start();
}
}
gives the following output
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleartool.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
stdout: cleardiff 2003.06.10+ (Tue Jul 13 14:02:05 2004)
Execution finished, exit code 0
hanging on the execution of the cleartool command. If instead cmd2 is changed to cleardiff the output is as expected
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
stdout: cleardiff 2003.06.10+ (Tue Jul 13 14:02:05 2004)
Execution finished, exit code 0
stdout: cleardiff 2003.06.10+ (Tue Jul 13 14:02:05 2004)
Execution finished, exit code 0
stdout: cleardiff 2003.06.10+ (Tue Jul 13 14:02:05 2004)
Execution finished, exit code 0
Question: Does anyone know why cleartool is hanging and how to fix?
You should consume the stdout and stderr in separate threads, otherwise you will experience blocking behaviour.
I suspect that's what's happening in this instance (and that it's unrelated to cleartool/cleardiff other than they're outputting stdout/err). See this answer for more information.
It seems you close the I/O streams BEFORE you start to wait for the termination. Also you read the stderr and stdout sequentially. However, the read to stderr blocks as there are no errors printed by the application and you don't move to the phase where you read the stdout. This deadlocks.
You could join the stderr and stdout via ProcessBuilder.redirectErrorStream() and then you need only to read stdout.
Your sample works in some cases because when you are blocked on the stderr, the application response on the stdout doesn't hit the size of the communication buffer. When the application quits, the stderr loop exits and the loop for stdout is able to retieve the contents of that buffer.