I'm writing a text/code editing program for my own use in Java/Swing, and was wondering how I would go about setting up a built-in C compiler inside it. I would likely use GCC or TCC as the compiler. Anyway, my question is- how would I actually implement the compiler? Would I use a library that gives Java access to command line commands? Are there such libraries and if so, which is the best/easiest to use?
Thanks.
Accessing command line is the easiest way.
Try something like this:
Process myProc = Runtime.getRuntime().exec(command);
Where command is some string you want to pass to the command line.
After that you can redirect output / input of that process to the some java buffers to have the full control.
myProc.getInputStream();
myProc.getOutputStream();
Typically IDE/Editor's don't implement the compilers. They will just execute the commands and pass the filename as argument (along with other necessary files). They also pipe/stream the output to a separate window/pane in the editor. So you need to integrate the compiler somehow not implement one. You can execute the commands in java using Runtime class. Start here.
Related
From what I read, there are a couple of ways to run java files in a node.js application. One way is to spawn a child process: (the java code is packaged with dependencies in an executable jar.)
var exec = require('child_process').exec, child;
child = exec('java -jar file.jar arg1 arg2',
function (error, stdout, stderr){
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if(error !== null){
console.log('exec error: ' + error);
}
});
The other way is to use the java - npm module (link), a wrapper over JNI (this will let me create objects, set and get attributes, run methods).
In a production environment, when I want my node.js (Express) server to call a java program (it just saves an image to the local directory), please advise me on which would be the better way to accomplish this (in terms of best practices). Also, there is a long list of arguments that I need to pass to the main class and doing that on the command line is a bit of a struggle. Should I make the java program read from an input file instead?
1) If you use exec, you will run an entire program, whereas if you use a JNI interface, you'll be able to directly interact with the libraries and classes in the jar and do things like call a single function or create an instance of a class. However, if you don't need anything like that, I think using exec is far simpler and will also run faster. Sounds like you just want to run the Java application as a standalone process, and just log whether the application finished successfully or with errors. I'd say it's probably better to just use exec for that. Executing a child process this way is also far better for debugging, debugging JNI errors can be very difficult sometimes.
2) As for whether or not to read arguments from a file, yes, it's usually better to read from some sort of file as opposed to passing in arguments directly. It's less prone to human error (ie. typing in arguments every time), and far more configurable. If someone like a QA engineer only needs to edit a config file to swap out options, they don't need to understand your entire codebase to test it. Personally I use config files for every Java program I write.
You can use deployment toolkit and run the jar through jnlp. https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/deployment_toolkit.html
Advantage of running jars through jnlp is the ability to pass parameters from javascript to your jar. In this way you can dynamically customize your java program.
For this kind of problem you'd want to approach it in the following way:
Is there a decent way to run processes with arguments in my language/framework
Is there a decent way to deal with the programs output?
From experience, a decent way to deal with arguments in a process is to pass them as an (string) array. This is advantageous in that you do not have to resort to unnecessary string interpolation and manipulation. It is also more readable too which is a plus in this problem setting.
A decent way to deal with output is to use a listener/event based model. This way, you respond appropriately to the events instead of having if blocks for stderr and stdout. Again, this makes things readable and let's you handle output in a more maintainable manner.
If you go a bit further into this, you will also have to solve a problem of how to inject environment variables into your target program. As an example, you might want to run the java with a debugger or with less memory in the future, so your solution would also need to cater for this.
This is just one way of solving this kind of problem. If node is your platform, then have a look at Child Process which supports all of these techniques.
We can run the whole java project by making .jar file of it and run it using the command in the shell and run that shell file. In order to run java code from nodejs project as we know project could be a mix of java, js modules.
Call exec() function in node to create a child process to execute the shell file having a command to run .sh file and can also pass some argument in it from use.eg;
let fileName = 'someFile.txt';
let userName = 'Charlie Angle';
exec(`sh run.sh --context_param
paramFilePath="./storage/${fileName}" --context_param userName="${userName}"`, (error, stdout, stderr) => {// Some code based on execution of above command})
You can simply call a java command , with classpath & arguments, using module node-java-caller, it embeds the call to spawn and will also automatically install java if not present on the system
https://github.com/nvuillam/node-java-caller
I want to use the org.apache.commons.exec Java library to call an executable. Does the CommandLine object protect against command line injection? For example, if I call:
String singleStringArgument = "-whatever;rm -rf ~/*"; // evil looking argument!
CommandLine cl = new CommandLine(new File(pathToExe,exeName));
cl.addArgument(singleStringArgument); // oh no!
Executor exe = new DefaultExecutor();
exe.execute(cl);
would rm -rf ~/* also run in addition to the intended command? If it does, what is the best way to protect against this?
The API says addArgument() "handles quoting" but I'm not sure what that means in this context. I could whip up a test case to see what happens on my linux box, but I want to be sure that it's safe on other platforms too.
; is a feature of the shell. If you don't create a command line around sh -c or something like it, you can't get injected into. It's not that commons is safe, its that you aren't even running the program with the vunerability.
Commons CLI is wrapping the Process class. The Process class is not documented to fire up the shell. It is documented to do an exec with specified arguments of what you tell it to.
As per a comment, one of the wonders of open source is that you can read the source. If version X of commons-CLI does what you like, depend on it, and don't upgrade without rechecking.
So you control the command (pathToExe) and are worried only about the argument? How well do you know the command? Is there any chance that it could exec another program? Is there any chance it could do something damaging even without invoking a secondary command? Does the program have any other vulnerabilities (buffer overflow, etc)?
As a general answer, this approach seems iffy to me, especially if you want this to work cross platform. If you know the command to be executed and can constrain the input, then you might be able to squeak by, but personally I wouldn't use this approach unless there was a really good reason to do so.
My suggestion is to make the program err on the side of safety if possible and only issue commands itself and not dumbly execute command fragments or pass on arguments issued by an end user. There are many variations of injection. ; is one already discussed. You can also use backticks (wrapping rm -rf ~/* in backticks makes the shell interpret it first)The user can also accidently or intentionally invoke aliases. The list of things that can go wrong is endless.
I'm writing a script to interact with GDB and need for GDB to think that it's connected to a terminal. I found some references online to C functions that can be used to do this but my program is written in Groovy (Java) and I want to avoid using the JNI interface. I thought a better way to do this would be to use expect.
As a script:
#!/usr/bin/env expect
eval spawn $argv
interact
When run from my script:
"expect -c 'eval spawn " + cmd + "; interact'".execute()
The problem with these scripts is that expect never seems to terminate. I would like for my expect wrapper to be generic so I don't want to trap on specific words. I also do not want to use the GDB/MI interface because I would like to generate a log of the GDB session that looks like you would see it from a terminal. How can I get my expect wrapper to terminate properly? Do I need to worry about quotes in the provided command or is spawn smart enough to figure out that an item in the list with spaces is still one argument?
You write that you don't want to use JNI. Did you consider using JNA? I never used it so far, but the description looks promising.
It's a bit of a kludge but maybe you can run gdb inside script.
Giving up and just using the MI interface
This question already has answers here:
how to change the name of a Java application process?
(10 answers)
Closed 8 years ago.
If a Java program is started, it get's in the system process-monitor the name java. Many Java-programs are that way hard to distinguish. So it would be nice, if a way exists, to set the name, that will be shown in the process-monitor. I'm aware that this may work different on different Operating Systems.
A simple way would be, if the java-interpreter would support a switch to set the name, like this:
java -processname MyProgram -jar MyProgram
But I couldn't find such a switch, so it is probably non-existant. An API in Java to set the process-name would be also fine.
So, so you have any suggestions?
I don't know if this is possible, but you could use a command line tool that comes with the JDK called 'jps'. It's like *nix ps, but just Java programs instead. jps -v shows all the arguments you have passed to java.
Also, I have seen people attach a "process name" to their java processes by adding an unused -Dmyprocessname to the args.
as #omerkudat said:
jps -v
prints out all java processes {processID, params list}
If the params list is not enough to recognize the applications you need,
try adding some dummy params when running them:
java -Dname=myApp -cp myApp.jar some.client.main.MainFrame
This will print like:
7780 MainFrame -Dname=myApp
and you can use the process ID to kill / monitor it.
You can do this with an LD_PRELOAD shim: https://github.com/airlift/procname
The shim simply calls the Linux-specific prctl() when the process starts:
static void __attribute__ ((constructor)) procname_init()
{
prctl(PR_SET_NAME, "myname");
}
The call has to happen on the main thread, so it isn't possible to do this from Java or even with a JVMTI agent, since those happen on a different thread.
When I first read this, the idea of changing the process name struck me as impossible. However, according to this ancient thread on the sun forum you can use C++ wrappers around the JVM executable to achieve this.
Though frankly, I wonder what your real problem is, as I'd guess there is a more standard solution then attempting to change the process name.
Your best option is something like launch4j
http://launch4j.sourceforge.net/
There is a bug logged in the sun bugtracker for this, but it's not high priority
http://bugs.sun.com/view_bug.do?bug_id=6299778
There are mainly 2 approaches: one is as already described: using tools like Launch4j, WinRun4J to create native Windows launchers.
Another approach that seems better is to use Apache Procrun to wrap the java application as a Windows service. During the install service process, we can give the process an meaningful name such as OurApp.exe.
All we need do is rename prunsrv.exe to OurApp.exe and replace every occurrence of prunsrv.exe in our install|start|stop|uninstall service scripts to MyApp.exe.
See more from Using Apache Procrun to Rename Process Name of a Java Program in Windows
If you want to use a different process name you'll have to create your own binary to launch your Java application using something like JSmooth.
Look at this question for a discussion of creating such binaries.
That's because Java applications aren't actually executable they're ran by the Java virtual machine which is why java appears in the process monitor, it's the host of your application.
Things like LimeWire however do but I think that's more down to GCJ - http://gcc.gnu.org/java/
I have a Java program that is mostly GUI and it shows data that is written to an xml file from a c++ command line tool. Now I want to add a button to the java program to refresh the data. This means that my program has to call the c++ functionality.
Is the best way to just call the program from java through a system call?
The c++ program will be compiled for mac os and windows and should always be in the same directory as the java program.
I would like to generate an executable can the c program be stored inside the jar and called from my program?
If you have access to the code and want an 'interactive' experience with the external program (e.g., make call, get results, make additional calls), investigate JNI, which allows you to call C or C++ code from a Java application by including & linking JNI juice to your C or C++ app with .
See:
http://en.wikipedia.org/wiki/Java_Native_Interface
http://www.acm.org/crossroads/xrds4-2/jni.html
If you really just need a "launch app and get results" sort of solution, check out Runtime.exec(), which lets you launch an external program & capture its output.
See:
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1
http://www.rgagnon.com/javadetails/java-0014.html
Assuming no better communication method is available (SOAP, ICE, Sockets, etc), I'd call the executable using Runtime.exec(). JNI can be used to interface directly, but I wouldn't recommended it. No you can't put an executable in the jar. Well you can, but you can't run it, since the shell doesn't know how to run it.
You may also want to look at the Java Native Access API (JNA).
To answer your final question, you can't run an executable from within your jar.
However, you can store it within your jar and extract it to a temporary directory/file prior to running it (check for its presence the first time and extract if necessary). This will simplify your distribution somewhat, in that you only have the jar to distribute, and ensures that you're running an executable that matches your jarred Java code.