Running a shellscript from a C++ application and check if it succeeds - c++

I am creating an interpreter for my extension to HQ9+, which has the following extra command called V:
V: Interpretes the code as Lua, Brainfuck, INTERCAL, Ruby, ShellScript, Perl, Python, PHP in that order, and if even one error has occoured, run the HQ9+-ABC code again
most of them have libraries, BF and INTERCAL can be interpreted without a library, but the problem lies in ShellScript. How can I run a shellscript from my C++ application ( =the HQ9+-ABC interpreter) and when it's done, get the error code (0 = succeded, all others = failed)? So something like this:
system(".tempshellscript738319939474");
if(errcode != 0) { (rerun code); }
can anyone help me? Thanks

From man system(3):
RETURN VALUE
The value returned is -1 on error (e.g. fork failed), and the return
status of the command otherwise. This latter return status is in the
format specified in wait(2). Thus, the exit code of the command will
be WEXITSTATUS(status). In case /bin/sh could not be executed, the
exit status will be that of a command that does exit(127).

system() returns a code depending on the success or failure of whatever you called.
http://www.cplusplus.com/reference/clibrary/cstdlib/system

I remember execve call working for shell scripts that had #! interpreter in their first line for an assignment at university. If you are using system, consider trying execve as well. wait on the pid of the script could help receiving the exit status.

Related

What is the safe way of get the return status from an executed shell command in c++

Since the function std::system(const char* command) from cstdlib doesn't guarantee that will return the correct return status from the shell, then how can I run a command in shell using c/c++ and have a guarantee that will give me the right return value?
In my case, for example, I ran a command with:
bool is_process_running(std::string p_name){
std::string command_str= "ps aux | grep '" + p_name + "' | egrep -v '(grep|bash)'";
int result(0);
result= system(command_str.c_str());
return result == 0;
}
If I run, for example, ps aux | grep 'my_process' | egrep -v '(grep|bash)' directly into the terminal and after that echo $?, I see it returning 0 because my_process is running and also returning 1 when I use a non running process. But, the code above returns a different value. This code used to work when I tested in CentOs 6 but now in CentOs 7 doesn't work anymore. So, what can I use to run the shell command and get the correct result?
I also found a solution using pidof command but I can't use this because pidof doesn't consider the parameters passed to my_process which I need since I have many instances of this process each with different arguments.
The problem is that the exit status of Bash isn't guaranteed to be the exit status of the last executed command. If there's an error in the command you pass, you can't really distinguish it from egrep failing to match anything.
What you need to do is to do is to both get the exit status and parse the output (both to standard output and standard error). This can be accomplished by copying much of what the system function does: First create a pipe for the output (both stderr and stdout could be using the same pipe), then fork a new process to run the shell, and then execute the shell and the pipeline.
In the parent process you wait for the child to exit, and get its exit status. If it's zero then you know everything worked fine, and you can discard all the output from the pipe. If it's non-zero you have to read the output from the pipe to see what happened, if there was some error except egrep failing.

What could cause unzip command returning -1 in my scenario?

I run unzip via a system() call in my C++ code in below format:
/usr/bin/unzip -o -q /<my_path_to_zip_file>/cfg_T-KTMAKUCB.zip -d /<my_path_to_dest>/../
This will almost 90% of times succeed. I cannot understand what could make it fail time to time with -1 return code. Any ideas?
According my local man system,
The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise.
and the POSIX spec says,
If a child process cannot be created, or if the termination status for the command language interpreter cannot be obtained, system() shall return -1 and set errno to indicate the error
Finally, the manpage for unzip lists various return codes, but -1 isn't among them.
If the command itself can't return -1, the problem is probably with the initial fork/exec, due to something like a system-wide or per-user limit (memory exhausted; process table full; maximum processes, open files or VM size limit for the user etc. etc).
You should be checking errno when system fails anyway. Running the whole thing under strace -f will also show what happens.

How do I make my c++ code know whether a command run from "system(cmd)" failed or not?

Let's assume I am running a unix command using system("foocmd param1") on c++.
If foocmd returns "Invalid argument" back to the terminal via stderr, then how do I get my c++ code to know whether foocmd failed?
Here is my attempted solution:
My assumption is that I should check whether anything got returned to stderr by calling the command.
To do that, I tried switching over to popen. Currently, this is the way I check. I first output my stderr into a file.
sprintf(cmd, "foocmd param1 2>temp.txt");
system(cmd);
Then I check if temp.txt is empty or not.
But there has to be a better way. Can anyone lend me a hand?
The usual way is to examine the return value of system():
If it's zero, the command executed successfully and exited with a status of 0.
If it's negative, there was a problem with system() itself, and you can't assume anything.
If it's positive, then you can use WEXITSTATUS() and related macros to find out how the process exited.
See the system(3) man page for the full details.
Most of the time, you are only interested in whether the command says it succeeded:
if (!system(cmd)) {
syslog(LOG_WARNING, "Command \"%s\" failed", cmd);
/* maybe some more error handling here */
goto err_return;
}

Is there a way to let IAR CSPY return an error code defined by executed user program?

I am using IAR EWARM's cspybat to run some unit tests for my embedded code using Unity. I would like an easy way for my build server to determine if the unit tests passed or failed. Is there a way for CSPY to return a nonzero error code if my unit tests fail? I have tried changing the return value in main() with no change. Is there a function I can call to force an error to be returned?
My cspybat batch file looks like this:
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.4\common\bin\cspybat" -f "C:\Work\Sandbox\ST\stmicroeval\_iar_ewarm_project\settings\Project.UnitTest.general.xcl" --backend -f "C:\Work\Sandbox\ST\stmicroeval\_iar_ewarm_project\settings\Project.UnitTest.driver.xcl"
Unfortunately, no.
I've solved this by replacing "exit" with a function that prints a specific pattern, plus the exit code. I then wrapped the call to cspybat into a script that 1) strips the output of the extra output and 2) exits with the desired exit code.
It's late 2020 and they still don't offer a mechanism to do this.
We solved it by including a macro file with the contents:
execUserExit()
{
__message "program exited with __exit_value = ", __exit_value:%d ;
}
And having our own exit variable in the code:
extern "C" int __exit_value=0xff;
That we set prior to calling exit() (though you could just write your own version of exit())
This makes the debugger always print SOMETHING, even if the program crashes on startup.
Then we parse with a python wrapper:
pattern = "__exit_value =\s([\-|0-9|a-f|A-F|x]*)"
retvalue = int(re.findall(pattern,process.stdout)[0])

How to Execute Linux commands in Django?

To execute Linux commands in Python we have great modules: os and subprocess. I have integrated Linux commands in the console based python program using both os and subprocess module however the same thing doesn't happen in Django. Take an example of this view:
def hello(request):
res = os.system('ls')
return render_to_response('thanks.html', {'res':res}, context_instance=RequestContext(request))
The only thing this view returns is 0. I have tried with subprocess too. The output I get is 0. What's wrong?
This is not a Django issue. That's what os.system does - it gives the return value of the system call, in this case 0 for a successful execution.
If you need to grab the output of an external program, you should use subprocess.check_output (2.7 only). However, if all you're interested in is a directory listing, there's a better way to do that, which is to use os.listdir.
0 is this case is the return code of the exit status which means "nothing is wrong" in this case.
According to os.system doc:
On Unix, the return value is the exit status of the process encoded in the format specified for wait(). Note that POSIX does not specify the meaning of the return value of the C system() function, so the return value of the Python function is system-dependent.
On Windows, the return value is that returned by the system shell after running command, given by the Windows environment variable COMSPEC: on command.com systems (Windows 95, 98 and ME) this is always 0; on cmd.exe systems (Windows NT, 2000 and XP) this is the exit status of the command run; on systems using a non-native shell, consult your shell documentation.