Is it possible to have a Java program communicate with terminal? - java

I know you can use terminal/cmd to pass in arguments to a Java program, but can you do it the other way, ie have a Java program pass info back to terminal?
More specfically I want to do something like this:
use terminal to launch and pass in value to a Java program
do stuff based on input and pass back a value
use that value to encrypt a file using terminal
repeat

To get your started:
Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method. - Java API
You can basically run anything in terminal using this class:
Process p = Runtime.getRuntime().exec(command, null);
Where command is like ffmpeg -help, for example.

The sort of equivalent of args passed to program in the start of main method is an Integer passed to program exit statement, being the return value of the program:
System.exit(0);
This number can be any Integer.
If you run your program by java yourProgram, you can get exit code by
echo $?

Related

Java - How would I take input from the main command line that I run my Java program with?

I was wondering how I would take additional input into a java program from the very line that I call the program to run from?
The input needs to be something like this:
java program abc.fsm <qwerty.txt
where I could run my program "program"
then save the two bits of text "abc.fsm" and "qwerty.txt" as strings then use them to later to call upon files and parse them

Calling a Java Program from Cobol

I'm trying to communicate Java and Cobol. I need to call a Java program (with paramaters) from Cobol.
I read some documentation from Microfocus:
http://supportline.microfocus.com/documentation/books/nx40/dijafc.htm
http://supportline.microfocus.com/documentation/books/nx40/dijaco.htm
But I didn't find a real solution, because I need to call an entire program and not a Java Class.
Thanks in advance.
Below is a sample program that will launch an EXE from within a COBOL97 application.
Check CallEXE demo in http://www.netcobol.com/support/code-samples/
When it comes to Microfocus...
One can not CALL an EXE from a Micro Focus INT or GNT, but you can CALL a Non-mainframe program (Micro Focus dialect in MFE) and issue a shell to DOS and from there either execute a command line that executes the EXE or execute the EXE file directly passed on the Micro Focus CALL (x'91' function code =35).
Also, you will not get back any passed parameters since once the DOS shell is closed, no parms can be returned. So the best way to get parms back is to write them to a file.
I am including a sample program that shows this x'91' FC=35 call. As you can see, you can execute a batch file or a command or an EXE directly.
Working-Storage Section.
1 Cmd-Line-Str.
2 Pic X(45)
* value 'RUN $IMSDIR\PCIMS RUNIMS BMP,DBUTIL,DEMO001T'.
* value 'run lorince'.
value 'dir c:\ /o > d.d'.
2 N-1 Pic X Value Low-Value.
1 Call-Func Pic X Comp-X Value 35.
1 Result Pic X Comp-X.
1 Cmd-Line-Len Pic X Comp-X Value 0.
Procedure Division.
P1.
Display Cmd-Line-Str upon Command-Line
Call x'91' using Result, Call-Func, Cmd-Line-Len
If Result = Zeroes
Display 'Call worked'
End-If
Goback.
I hope the post gives you some more information, I have only mainframe knowledge and haven't tried any of this above.
The link you posted explains very well about how we can instantaite a java class. If you are concerned about parameters, then write the Java Class with parameteric constructor and pass the parameters while you instantiate the Class from Cobol.
If you are confused about Java Class and Java Program, then you need to know that Java programs are compiled into .class files at the most you have executable jars containing .class files. But there is nothing like .exe for java.

Returning values from a java program back to a batch file

In the good old days of C you had int main(...) as the entry function and you could call the executable from a batch file and check %errorlevel% in that batch file which would contain the return value.
In java I compile my java application to something.jar and mark a function like public static void main(String[] rawArgs) as the entry point. I then call java -jar something.jar from the batch file. I can even append command line arguments if I want to.
But now I can't check %errorlevel% since my main function is returning a void.
I suppose this is all perfectly logical given that everything is running in a virtual machine and that is the actual executable rather than something.jar.
I can use System.exit(...) to achieve my original aim.
My question is this: Is there a better way of doing this? Killing off the virtual machine seem heavy handed. What if the code runs server side? Am I missing a cute function like Runtime.SetErrorLevel which does what I want?
System.exit() is the correct way to do what you want - a process can only return an error condition when it exits anyway, so what would be the point in specifying that code anywhere else?
Simply use System.exit() with a non zero parameter to indicate the error level - there's no need to look for an alternative way. If you try to work around it you're just going to end up with horrible native hacks that aren't portable yet accomplish the same thing as System.exit().
Place a call to System.exit() just before the end of your main function.
Declare a native function in java, static native void SetErrorLevel(int level);, generate the JNI headers using javah.exe and implement the function in C which sets the %errorlevel% environment variable in your process.
Then terminate normally.

Java String execution in Linux terminal

I am using StringBuilder to create a string and then trying to execute the string on Linux terminal. But instead of executing whole command, it executed half command and then terminates it. This is my java code snippet:
moteCommand.append("CFLAGS+=-DCC2420_DEF_CHANNEL=1");
moteCommand.append(" ");
moteCommand.append("make telosb install.");
moteCommand.append(moteIdList.get(i).toString());
moteCommand.append(" bsl,");
moteCommand.append(moteAddrList.get(i).toString());
String moteCommand2 = moteCommand.toString();
Process moteProgProcess = Runtime.getRuntime().exec(moteCommand2, null,"/opt/tinyos-2.x/apps/XXX/);
It gives me this error:
Cannot run program "CFLAGS+=-DCC2420_DEF_CHANNEL=1" (in directory "/opt/tinyos-2.x/apps/xxx"): java.io.IOException: error=2, No such file or directory
I don't understand why system process is trying to execute only half of the string. Please let me know if anybody knows the reason.
Thanks.
When you call Runtime.exec(), the characters up to the first space must be the name of the program you want to launch. After that, each "part" between spaces is a separate argument. Note that calling Runtime.exec() is completely different from typing a command in bash (or any other shell...) and pressing enter!! If you type a command that works fine in bash, it doesn't mean it will work with Runtime.exec(). For example, shell commands (which are not external programs) won't work in Runtime.exec().
What you should do is use ProcessBuilder.
Instantiate it, manipulate its Map that represents the environment options (ie, the things you are passing before the command name, such as the cflags, and anything else you might want), set the command name, give the arguments one at a time (the arguments won't get split at spaces, so you can pass paths containing spaces, for instance), etc. You can manipulate the stdin, stdout and stderr in many different ways (such as: use the same as those used by the Java process; or get instances of InputStream and OutputStream to write to and read from the process; or pipe them), and run the process.
Something along the lines:
final ProcessBuilder pb = new ProcessBuilder("make", "telosb", "install" blablablabla);
final Map<String, String> env = pb.environment();
env.put("CFLAGS", "....your options....");
pb.start(); // take the Process instance, and you will be able to read the output, wait for it to finish, get the exit code, etc

Java exec on Unix

I have the Java code below running on Unix (both AIX and Linux), but it doesn't work. If I run this code the file q1.01 is not compressed, and I don't get any exceptions thrown (The file q1.01 exists, and I expect to find the file q1.01.Z after the command runs.) At the command prompt if I type "which compress" it reports back with "/usr/bin/compress". If I type the command "/usr/bin/compress q1.01" at the Unix prompt it works fine. Any ideas on what might be wrong?
String cmd = "/usr/bin/compress q1.01";
Runtime.getRuntime().exec(cmd);
[Later edit: the problem was in the initial description; the OP was passing a wildcard and not q.01. So my answer below is wrong, except for the part in bold. I'm leaving it so the comments after it will make sense.]
It's trying to run /usr/bin/compress as the program name without arguments.
There are many forms of the Runtime.exec() method. You're using the .exec(String) version, which just takes the executable. Instead, you need to use the .exec(String[]) array version, which takes the executable in String[0] and the parameters in String[1..].
.exec() wants a String array for passing arguments.
Try
String[] cmd = new String[] { "/usr/bin/compress", "q1.01" };
Runtime.getRuntime().exec(cmd);
Note that .exec does not call the local command shell. That means we have to do, among other things, wildcard expansion and even some argument parsing before calling .exec(). This is why you can't just pass it your full command line.
There were a couple of problems. One was that I had tried using wildcards, and since the shell isn't invoked they weren't being expanded. The other problem was that I had created very small test files like this: "echo 'abc' >q1.01". This file was so small that compress couldn't compress it any further and so left it alone. (Stupidly, I think when I typed in the command at the shell I used a different filename, which did compress.)
Thanks everyone for the answers. It did help!
You probably need to use an absolute path to the file. Capture the output though, to see what the problem is - see this page for info on how to do that.
This site may be able to provide some clues.
If the process input stream is null, I suspect that Java wasn't even able to spawn the subprocess. What does Process#exitValue() return?
I'd recommend using strace to see what actually happens on the system-call level. The actual exec() arguments and return code would be especially interesting to see.

Categories

Resources