I am trying to port a C program to android using JNI. I have been able to set up the program and get java and c working fine together. The problem is I need to be able to use STDIN since the C program reads input from STDIN and returns a response through STDOUT (C program is a server-client application). I don't know if it is worth mentioning but the C program uses STDIN_FILENO file descriptor for reading input from STDIN. How do I read from STDOUT and WRITE to STDIN using Java?
I did some research and found some vague explanation at the following link: https://groups.google.com/forum/#!topic/android-ndk/Brm6jPr4C0Y that I don't understand.
Here's is the C code https://github.com/unekwu/kemi/blob/master/jni/dnscat/dnscat.c#L1270
More Details
The C program is usually run from command line like
dnscat --dns <ip> <port>
After which it starts listening for messages from the user. Normally entered from stdin.
Now in my Android app, I'm able to run it with JNI by calling main and different name and passing ann array of strings to it. I'v verify the program starts up correcting. The problem is how I'll send the messages to the program since there's no stdin on android.
I've created a project in github, which you can download from here.
It creates 2 named pipes (FIFO), one for input and other for output.
It opens up one end of the pipe in write only mode in native code and other end of the pipe in read only mode in Java code. The file descriptor in native code is mapped to STDOUT i.e. 1, thereafter any writes to STDOUT in native code, will be redirected to other end of pipe which can read in Java code.
It opens up one end of the pipe in read only mode in native code and other end of the pipe in write only mode in Java code. The file descriptor in native code is mapped to STDIN i.e. 0, thereafter any writes to other end of pipe in Java code, will be read by native code using STDIN.
To achieve STDOUT redirection:
Native Code:
/*
* Step 1: Make a named pipe
* Step 2: Open the pipe in Write only mode. Java code will open it in Read only mode.
* Step 3: Make STDOUT i.e. 1, a duplicate of opened pipe file descriptor.
* Step 4: Any writes from now on to STDOUT will be redirected to the the pipe and can be read by Java code.
*/
int out = mkfifo(outfile, 0664);
int fdo = open(outfile, O_WRONLY);
dup2(fdo, 1);
setbuf(stdout, NULL);
fprintf(stdout, "This string will be written to %s", outfile);
fprintf(stdout, "\n");
fflush(stdout);
close(fdo);
Java Code:
/*
* This thread is used for reading content which will be written by native code using STDOUT.
*/
new Thread(new Runnable() {
@Override
public void run() {
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(mOutfile));
while(in.ready()) {
final String str = in.readLine();
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(RedirectionJni.this, str, Toast.LENGTH_LONG).show();
}
});
}
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
To achieve STDIN redirection:
Native Code:
/*
* Step 1: Make a named pipe
* Step 2: Open the pipe in Read only mode. Java code will open it in Write only mode.
* Step 3: Make STDIN i.e. 0, a duplicate of opened pipe file descriptor.
* Step 4: Any reads from STDIN, will be actually read from the pipe and JAVA code will perform write operations.
*/
int in = mkfifo(infile, 0664);
int fdi = open(infile, O_RDONLY);
dup2(fdi, 0);
char buf[256] = "";
fscanf(stdin, "%*s %99[^\n]", buf); // Use this format to read white spaces.
close(fdi);
Java Code:
/*
* This thread is used for writing content which will be read by native code using STDIN.
*/
new Thread(new Runnable() {
@Override
public void run() {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mInfile)));
String content = "This content is written to " + mInfile;
out.write(content.toCharArray(), 0, content.toCharArray().length);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Let me know if you need any help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With