I was trying to use https://developer.rackspace.com/blog/displaying-prepared-code-with-syntax-highlighting-on-android/ to display some code in html, so I wrote a custom formatter in Java, which has, among other things, this procedure:
String code2html( String s ) throws Exception {
if ( s == null || s.length() == 0 ) return "";
String t;
PrintWriter w = new PrintWriter(Konst.FPATH+"tmp.txt","UTF-8");
w.println(s);
w.close();
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("vim -c \"let html_use_css=0\" -c \"TOhtml\" -c \"w\" "+Konst.FPATH+"tmp.txt.html"+" -c \"wq\" -c \"q\" "+Konst.FPATH+"tmp.txt");
StringBuilder sb = new StringBuilder();
BufferedReader b = new BufferedReader(new FileReader(Konst.FPATH+"tmp.txt.html"));
while ( (t=b.readLine())!=null && !(t.length()>=5&&t.substring(0,5).equals("<body")) );
do {sb.append(t+"\n");} while ( (t=b.readLine())!=null && !(t.length()>=6&&t.substring(0,6).equals("</body")) );
sb.append(t);
return sb.toString();
}
However, I get FileNotFoundException for tmp.txt.html file, although the tmp.txt is created allright. Running the above vim command from commandline produces the desired result. What can be done?
EDIT: I added int retVal = pr.exitValue() and got Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited
EDIT: Ha, I've read this wonderful document: http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2, implemented their recipe for dealing with this problem, and what I get is
ERROR>Vim: Warning: Output is not to a terminal
ERROR>Vim: Warning: Input is not from a terminal
Bram Moolenaar answers similar question on http://vim.1045645.n5.nabble.com/Vim-Warning-Output-is-not-to-a-terminal-td4648615.html
He says "If both input and output are redirected, you are really stuck".
I found a workaround by using gvim rather than terminal vim, and rewriting my above code as
String code2html( String s ) throws Exception {
if ( s == null || s.length() == 0 ) return "";
String t;
PrintWriter w = new PrintWriter(Konst.FPATH+"tmp.txt","UTF-8");
w.println(s);
w.close();
Runtime rt = Runtime.getRuntime();
String T;
try {
Process pr = rt.exec(T = "gvim -c \"let html_use_css=0\" -c \"TOhtml\" -c \"wqx\" -c \"q\" -c \"q\" " + Konst.FPATH + "tmp.txt");
FileOutputStream fos;
StreamGobbler errorGobbler = new StreamGobbler(pr.getErrorStream(),"ERROR");
StreamGobbler outputGobbler = new StreamGobbler(pr.getInputStream(),"OUTPUT",fos=new FileOutputStream(Konst.FPATH+"garbage.out"));
errorGobbler.start();
outputGobbler.start();
int exitVal = pr.waitFor();
System.out.println("ExitValue: "+exitVal);
fos.flush();
fos.close();
StringBuilder sb = new StringBuilder();
BufferedReader b = new BufferedReader(new FileReader(Konst.FPATH + "tmp.txt.html"));
while ((t = b.readLine()) != null && !(t.length() >= 5 && t.substring(0, 5).equals("<body"))) ;
do {
sb.append(t + "\n");
} while ((t = b.readLine()) != null && !(t.length() >= 6 && t.substring(0, 6).equals("</body")));
sb.append(t);
return sb.toString();
}
catch ( Throwable e ) {
e.printStackTrace();
}
return "";
}`
Related
In the code below, the author uses Runtime to call a sub-process. But I don't understand why he uses StreamGobbler. What will happen if replace it by InputStream? Please help me, thanks!
public class GoodWindowsExec
{
public static void main(String args[])
{
try
{
String osName = System.getProperty("os.name" );
System.out.println("osName: " + osName);
String[] cmd = new String[3];
if(osName.equals("Windows XP") ||osName.equals("Windows 2000"))
{
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
else if( osName.equals( "Windows 98" ) )
{
cmd[0] = "command.com" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
Runtime rt = Runtime.getRuntime();
System.out.println("Execing " + cmd[0] + " " + cmd[1]+ " " + cmd[2]);
Process proc = rt.exec(cmd);
// any error message?
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR"); //Can I replace StreamGobbler by InputStream?
// any output?
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); //As above
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t){
t.printStackTrace();
}
}
}
BufferedReader brNormal = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s = null;
while ((s = brNormal.readLine()) != null) {
logger.info("RawToRgbConverter.exe", s);
}
brNormal.close();
BufferedReader brError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((s = brError.readLine()) != null) {
logger.error("RawToRgbConverter.exe", s);
}
brError.close();
Even as I don't know the StreamGobbler class, this is obviously a threaded implementation to copy the output and error streams to a given target. Thus, no you cannot simply replace it, as the multi-threading is indeed necessary. A simple input stream would just sit there, but not actually do anything.
Note however, that this complete solution is outdated since Java 1.5 which introduced the ProcessBuilder and the automatic redirects. See the javadoc at https://docs.oracle.com/javase/8/docs/api/
I'm implementing a terminal "emulator"/"launcher" in my app. I want to let the user to use all android shell commands. This works great, until I use the "su" command. here is the source code:
Code:
ProcessBuilder processBuilder = new ProcessBuilder(input);
processBuilder.directory(info.currentDirectory);
Process process;
try {
process = processBuilder.start();
} catch (IOException e) {
return 1;
}
process.waitFor();
InputStream i = process.getInputStream();
InputStream e = process.getErrorStream();
BufferedReader ir = new BufferedReader(new InputStreamReader(i));
BufferedReader er = new BufferedReader(new InputStreamReader(e));
String s = null;
output = "";
for(int count = 0; count == 0 || s != null; count++) {
s = ir.readLine();
if(s != null) {
if(count == 0)
output = output.concat(mContext.getString(R.string.output_label) + "\n");
output = output.concat(s + "\n");
}
}
s = null;
for(int count = 0; count == 0 || s != null; count++) {
s = er.readLine();
if(s != null) {
if(count == 0)
output = output.concat(mContext.getString(R.string.error_label) + "\n");
output = output.concat(s + "\n");
}
}
process.destroy();
Main thread is blocked forever in any case: if I call only process.waitFor, and if I use one of the InputStream objects.
What's the problem? SU permissions are granted normally...
I am trying to compile and execute C , C++ and Java codes taken as argument to a Java file and then check that the generated solution is correct or not as most of the website judge the solutions.Please anybody can tell me why my code is going in infinite loop and no out put is coming in file_name_output.txt. My other all files are correct as i have tested them by running the program on terminal.Here is my code :
import java.io.*;
import java.util.Scanner;
class test
{
public static void main(String args[])
{
String s=null,file_name,extension;
int pos = args[0].lastIndexOf(".");
extension = args[0].substring(pos+1);
file_name = args[0].substring(0,pos);
int lang = 0; // 1 -> c,c++ , 2 -> java
try
{
Process compile = null;
switch(extension)
{
case "c" : compile = Runtime.getRuntime().exec("gcc -g "+ args[0] + " -o "+file_name+" -lm");
lang = 1;
break;
case "cpp" : compile = Runtime.getRuntime().exec("g++ -g "+ args[0] + " -o "+file_name);
lang = 1;
break;
case "java" : compile = Runtime.getRuntime().exec("javac "+ args[0]);
lang = 2;
}
BufferedReader stdError = new BufferedReader(new InputStreamReader(compile.getErrorStream()));
if((s = stdError.readLine()) != null)
{
System.out.println("Compile Time Error OR Warning : ");
System.out.println(s);
while((s = stdError.readLine()) != null)
{
System.out.println(s);
}
}
double startTime, run_time;
Process run;
if(lang == 1)
{
startTime = System.nanoTime();
run = Runtime.getRuntime().exec("./"+file_name+" < "+file_name+"_input.txt > "+file_name+"_output.txt");
run_time = (System.nanoTime()-startTime)/(double)Math.pow(10,6);
}
else
{
startTime = System.nanoTime();
run = Runtime.getRuntime().exec("java "+file_name+" < "+file_name+"_input.txt > "+file_name+"_output.txt");
run_time = (System.nanoTime()-startTime)/(double)Math.pow(10,6);
}
System.out.println("RunTime : "+ run_time+" ms");
BufferedReader out_put = new BufferedReader(new FileReader(new File(file_name+"_output.txt")));
BufferedReader run_stdError = new BufferedReader(new InputStreamReader(run.getErrorStream()));
if(( s = run_stdError.readLine()) != null)
{
System.out.println("Runtime Error : ");
System.out.println(s);
while((s = run_stdError.readLine()) != null )
{
System.out.println(s);
}
}
else if((s = out_put.readLine()) != null)
{
String s_string = null;
int failed = 0;
File fs = new File(file_name+".txt");
BufferedReader br = new BufferedReader(new FileReader(fs));
if((!s.equals(s_string = br.readLine())))
{
failed = 1;
}
while(((s = out_put.readLine()) != null) & ((s_string = br.readLine()) != null) & (failed == 0))
{
if(!s.equals(s_string) )
{
failed = 1;
break;
}
}
if((failed == 1) || s != null || s_string != null)
{
System.out.println("Submmision Failed : ");
System.out.println("Either Output Is Wrong.\nOR\nYour Output Is Not According To The Given Format. ");
System.exit(0);
}
else
{
System.out.println("Submission Successful.");
}
}
}
catch(IOException e)
{
System.out.println("Some Error Has Occured : ");
e.printStackTrace();
System.exit(-1);
}
}
}
Diagnosis
Your program is not in an endless loop, it is blocking, and this is the line where it happens:
s = run_stdError.readLine()
unless there's something on the subprocess's stderr, this is going to block until the process dies. However, while waiting here you don't consume the process's stdout. It fills its output buffer and blocks.
The result: an interprocess deadlock.
Suggested fix
Use a ProcessBuilder and use its API to achieve redirection into files with no effort of your own. You have the redirectOutput(File) and redirectError(File) methods in there.
ping and date returned output, but it's not returning anything from "ls" or "pwd". What I want to do ultimately is run an SSH command. Any idea what I am missing below?
//Works and shows the output
executeCommand("ping -c 3 " + "google.com");
//Works and shows the output
executeCommand("date");
//Does not work. No output
executeCommand("sudo ls");
//Does not work. No output
executeCommand("ls");
private void executeCommand(String command) {
StringBuffer output = new StringBuffer();
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();
}
Log.d("Output", "Output: " + output.toString());
}
I have two solutions
first solution (you need Java 7):
...
ProcessBuilder pb = new ProcessBuilder("ls");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();
second solution:
Process p=Runtime.getRuntime().exec("ls");
InputStream is = p.getInputStream();
int c;
StringBuilder commandResponse = new StringBuilder();
while( (c = is.read()) != -1) {
commandResponse.append((char)c);
}
System.out.println(commandResponse);
is.close();
For my server coded in java I want to add a console. I connect to my server using a socket.
Here is the code I've made for the console:
On my server:
public class ServerConsole
{
public String exec(String[] cmd)
{
try
{
Process child = Runtime.getRuntime().exec(cmd);
InputStream in = child.getInputStream();
StringBuffer buffer = new StringBuffer();
int c;
while ((c = in.read()) != -1)
{
buffer.append((char)c);
}
in.close();
return buffer.toString();
}
catch (Exception e) {}
return "FAILED";
}
}
This class execute the given command and returns a string that contains the content of the console after execution.
I call this method like that:
String cmd_data_cmd = inputStream.readUTF();
String[] dataCmd = cmd_data_cmd.split("#");
OSCmd osCmd = new OSCmd();
outputStream.writeUTF(osCmd.exec(dataCmd));
Where inputStream is the stream I use with my socket. It works well!
Now, on the client side, I've made that:
String[] cmd = cmd_input.getText().split(" ");
String new_cmd = "";
for (String part : cmd)
new_cmd += (new_cmd.equals("") ? "": "#") + part;
this.outputSocket.writeUTF(new_cmd);
DataInputStream result_input = new DataInputStream(this.input);
String tmp = result_input.readUTF();
System.out.println(tmp);
This should returns me the result displayed in the console but actually, nothing happens. It just freezes when I start that part of code.
Any idea how to do that?
Thanks.
Here is the solution:
String[] cmd_exec = {};
String os_name = System.getProperty("os.name").toLowerCase();
if (os_name.indexOf("win") >= 0)
cmd_exec = new String[]{"cmd.exe", "/c", cmd};
else if (os_name.indexOf("mac") >= 0)
cmd_exec = new String[]{"/usr/bin/open", "-a", cmd};
else if (os_name.indexOf("nix") >= 0 || os_name.indexOf("nux") >= 0)
cmd_exec = new String[]{"/bin/bash", cmd};
else if (os_name.indexOf("sunos") >= 0)
cmd_exec = new String[]{"/bin/bash", cmd};
Process child = Runtime.getRuntime().exec(cmd_exec);
String line;
while ((line = stdInput.readLine()) != null)
{
buffer.append("\t" + new String(line.getBytes("UTF-8"), "UTF-8") + "\n");
}
stdInput.close();
while ((line = stdError.readLine()) != null)
{
buffer.append("\t" + new String(line.getBytes("UTF-8"), "UTF-8") + "\n");
}
stdError.close();
child.destroy();
Hope this will help someone else.