WEXITSTATUS always returns 0 - c++

I am forking a process and running a wc command using execl. Now under correct arguments, it runs fine, but when I give a wrong file name, it fails, but in both the cases the return value of
WEXITSTATUS(status)
is always 0.
I believe there is something wrong with what I am doing, but I'm not sure what is. Reading man pages and Google suggests that I should get a correct value as per the status code.
Here is my code:
#include <iostream>
#include <unistd.h>
int main(int argc, const char * argv[])
{
pid_t pid = fork();
if(pid <0){
printf("error condition");
} else if(pid == 0) {
printf("child process");
execl("/usr/bin/wc", "wc", "-l", "/Users/gabbi/learning/test/xyz.st",NULL);
printf("this happened");
} else {
int status;
wait(&status);
if( WIFEXITED( status ) ) {
std::cout << "Child terminated normally" << std::endl;
printf("exit status is %d",WEXITSTATUS(status));
return 0;
} else {
}
}
}

If you supply a name of non existing file to execl() as 1st argument it fails. If this happens the program leaves without returning any specifiy value. So the default of 0 is returned.
You could fix the for example like this:
#include <errno.h>
...
int main(int argc, const char * argv[])
{
pid_t pid = fork();
if(pid <0){
printf("error condition");
} else if(pid == 0) {
printf("child process");
execl(...); /* In case exec succeeds it never returns. */
perror("execl() failed");
return errno; /* In case exec fails return something different then 0. */
}
...

You are not passing the file name from argv to the child process
Instead of
execl("/usr/bin/wc", "wc", "-l", "/Users/gabbi/learning/test/xyz.st",NULL);
Try this,
execl("/usr/bin/wc", "wc", "-l", argv[1],NULL);
The output I got on my machine
xxx#MyUbuntu:~/cpp$ ./a.out test.txt
6 test.txt
Child terminated normally
exit status is 0
xxx#MyUbuntu:~/cpp$ ./a.out /test.txt
wc: /test.txt: No such file or directory
Child terminated normally
exit status is 1

This was an xcode issue, running from console works fine. I am a Java guy, doing some assignments in CPP. Nevertheless, it might come handy to someone getting stuck at similar issue.

Related

How to a run command on Linux terminal from a C/C++ program [duplicate]

I want to execute another program within C code.
For example, I want to execute a command
./foo 1 2 3
foo is the program which exists in the same folder, and 1 2 3 are arguments.
foo program creates a file which will be used in my code.
How do I do this?
For a simple way, use system():
#include <stdlib.h>
...
int status = system("./foo 1 2 3");
system() will wait for foo to complete execution, then return a status variable which you can use to check e.g. exitcode (the command's exitcode gets multiplied by 256, so divide system()'s return value by that to get the actual exitcode: int exitcode = status / 256).
The manpage for wait() (in section 2, man 2 wait on your Linux system) lists the various macros you can use to examine the status, the most interesting ones would be WIFEXITED and WEXITSTATUS.
Alternatively, if you need to read foo's standard output, use popen(3), which returns a file pointer (FILE *); interacting with the command's standard input/output is then the same as reading from or writing to a file.
The system function invokes a shell to run the command. While this is convenient, it has well known security implications. If you can fully specify the path to the program or script that you want to execute, and you can afford losing the platform independence that system provides, then you can use an execve wrapper as illustrated in the exec_prog function below to more securely execute your program.
Here's how you specify the arguments in the caller:
const char *my_argv[64] = {"/foo/bar/baz" , "-foo" , "-bar" , NULL};
Then call the exec_prog function like this:
int rc = exec_prog(my_argv);
Here's the exec_prog function:
static int exec_prog(const char **argv)
{
pid_t my_pid;
int status, timeout /* unused ifdef WAIT_FOR_COMPLETION */;
if (0 == (my_pid = fork())) {
if (-1 == execve(argv[0], (char **)argv , NULL)) {
perror("child process execve failed [%m]");
return -1;
}
}
#ifdef WAIT_FOR_COMPLETION
timeout = 1000;
while (0 == waitpid(my_pid , &status , WNOHANG)) {
if ( --timeout < 0 ) {
perror("timeout");
return -1;
}
sleep(1);
}
printf("%s WEXITSTATUS %d WIFEXITED %d [status %d]\n",
argv[0], WEXITSTATUS(status), WIFEXITED(status), status);
if (1 != WIFEXITED(status) || 0 != WEXITSTATUS(status)) {
perror("%s failed, halt system");
return -1;
}
#endif
return 0;
}
Remember the includes:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
See related SE post for situations that require communication with the executed program via file descriptors such as stdin and stdout.
You can use fork() and system() so that your program doesn't have to wait until system() returns.
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char* argv[]){
int status;
// By calling fork(), a child process will be created as a exact duplicate of the calling process.
// Search for fork() (maybe "man fork" on Linux) for more information.
if(fork() == 0){
// Child process will return 0 from fork()
printf("I'm the child process.\n");
status = system("my_app");
exit(0);
}else{
// Parent process will return a non-zero value from fork()
printf("I'm the parent.\n");
}
printf("This is my main program and it will continue running and doing anything i want to...\n");
return 0;
}
system() executes a shell which is then responsible for parsing the arguments and executing the desired program. To execute the program directly, use fork() and exec() (which is what system() uses to execute the shell as well as what the shell itself uses to execute commands).
#include <unistd.h>
int main() {
if (fork() == 0) {
/*
* fork() returns 0 to the child process
* and the child's PID to the parent.
*/
execl("/path/to/foo", "foo", "arg1", "arg2", "arg3", 0);
/*
* We woundn't still be here if execl() was successful,
* so a non-zero exit value is appropriate.
*/
return 1;
}
return 0;
}
In C
#include <stdlib.h>
system("./foo 1 2 3");
In C++
#include <cstdlib>
std::system("./foo 1 2 3");
Then open and read the file as usual.
How about like this:
char* cmd = "./foo 1 2 3";
system(cmd);
Here's the way to extend to variable args when you don't have the args hard coded (although they are still technically hard coded in this example, but should be easy to figure out how to extend...):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int argcount = 3;
const char* args[] = {"1", "2", "3"};
const char* binary_name = "mybinaryname";
char myoutput_array[5000];
sprintf(myoutput_array, "%s", binary_name);
for(int i = 0; i < argcount; ++i)
{
strcat(myoutput_array, " ");
strcat(myoutput_array, args[i]);
}
system(myoutput_array);

the return value of a child process

I am new to fork and exec, and I tried the following program.
Program 1:
int main(int argc, char *argv[]){
pid_t pid;
int status;
pid = fork();
if(pid == 0){
printf("new process");
execv("p1",argv);
}
else{
pid_t pr = wait(&status);// I am trying to get the exit value
// of the sub process.
printf("the child process exit with %d",status);
printf("father still running\n");
}
}
Program 2:
int main(){
std::cout<<"I am the new thread"<<std::endl;
sleep(1);
std::cout<<"after 1 second"<<std::endl;
exit(1);
}
I run the first program, and the output is "the child process exit with 256". Why is the result 256 instead of 1? If I change exit(1) to exit(2), the result becomes 512, why is that? It only worked if I return 0.
The status value you get back from the wait system call is not necessarily what your child process exited with.
There are a number of other pieces of information that can be returned as well, such as:
did the process terminate normally?
was it terminated by a signal?
what was the signal that terminated it?
did it dump core?
In order to extract the exit code, you use a macro:
WEXITSTATUS(status)
That, and the macros that can give you more information, should be available on the wait man-page, such as the one here.

How to get pid of process executed with system() command in c++

When we use system() command, program wait until it complete but I am executing a process using system() and using load balance server due to which program comes to next line just after executing system command. Please note that that process may not be complete.
system("./my_script");
// after this I want to see whether it is complete or not using its pid.
// But how do i Know PID?
IsScriptExecutionComplete();
Simple answer: you can't.
The purpose of system() is to block when command is being executed.
But you can 'cheat' like this:
pid_t system2(const char * command, int * infp, int * outfp)
{
int p_stdin[2];
int p_stdout[2];
pid_t pid;
if (pipe(p_stdin) == -1)
return -1;
if (pipe(p_stdout) == -1) {
close(p_stdin[0]);
close(p_stdin[1]);
return -1;
}
pid = fork();
if (pid < 0) {
close(p_stdin[0]);
close(p_stdin[1]);
close(p_stdout[0]);
close(p_stdout[1]);
return pid;
} else if (pid == 0) {
close(p_stdin[1]);
dup2(p_stdin[0], 0);
close(p_stdout[0]);
dup2(p_stdout[1], 1);
dup2(::open("/dev/null", O_RDONLY), 2);
/// Close all other descriptors for the safety sake.
for (int i = 3; i < 4096; ++i)
::close(i);
setsid();
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(1);
}
close(p_stdin[0]);
close(p_stdout[1]);
if (infp == NULL) {
close(p_stdin[1]);
} else {
*infp = p_stdin[1];
}
if (outfp == NULL) {
close(p_stdout[0]);
} else {
*outfp = p_stdout[0];
}
return pid;
}
Here you can have not only PID of the process, but also it's STDIN and STDOUT. Have fun!
Not an expert on this myself, but if you look at the man page for system:
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed
You can go into the background within the command/script you're executing (and return immediately), but I don't think there's a specific provision in system for that case.
Ideas I can think of are:
Your command might return the pid through the return code.
Your code might want to look up the name of the command in the active processes (e.g. /proc APIs in unix-like environments).
You might want to launch the command yourself (instead of through a SHELL) using fork/exec
As the other answers said, std::system blocks until complete anyway. However, if you want to run the child process async and you are ok with boost you can use boost.process (ref):
#include <boost/process.hpp>
namespace bp = boost::process;
bp::child c(bp::search_path("echo"), "hello world");
std::cout << c.id() << std::endl;
// ... do something with ID ...
c.wait();
You can check exit status of your command by following code :
int ret = system("./my_script");
if (WIFEXITED(ret) && !WEXITSTATUS(ret))
{
printf("Completed successfully\n"); ///successful
}
else
{
printf("execution failed\n"); //error
}

waitpid does not appear to be wating

I have a simple function - its purpose is to copy a file to a .old before overwriting it. Because i'm lazy (and an answer on here suggested it) I fork and use cp to do the work.
Then i call waitpid and check the return codes.
The code calling this calls my copy function, then immediately opens the file for reading. Somehow the calling code seems to run before the cp call - the new file is what gets copied.
The best example is if neither file nor backup exist. Both are created and contain what my save call outputs.
I am struggling to see where I have gone wrong, help would be appreciated.
copy_old();
std::ofstream savefile (SETTINGS_LOCATION);
if (savefile.is_open())
{
savefile << ...
void settings::copy_old()
{
int childExitStatus;
pid_t pid;
pid = fork();
if (pid == 0) { /* child */
execl("/bin/cp", "/bin/cp", "-f", SETTINGS_LOCATION, SETTINGS_LOCATION_B, (char *)0);
}
else if (pid < 0) {
ERR("Could not Backup Previous Settings");
}
else {
pid_t ws = waitpid( pid, &childExitStatus, WNOHANG);
if (ws == -1)
{
ERR("Could not Backup Previous Settings1");
}
if( !WIFEXITED(childExitStatus) || WEXITSTATUS(childExitStatus)) /* exit code in childExitStatus */
{
ERR("Settings backup may have been unsuccessful");
}
}
}
Of course waitpid isn't waiting. You told it not to:
pid_t ws = waitpid( pid, &childExitStatus, WNOHANG);
WNOHANG means "don't wait". Change that WNOHANG to 0 if you want waitpid to wait.

calling execve() + changing PWD

I want to write a program A which executes another program B.
It is very important to execute program B from it's directory, cause it turns on program BB who sits in the same directory of B.
I mean:
./B will work
./b/B won't work
I thought about two ways to do so:
do fork(), change the PWD in env, and then call execv()
do fork(), create a temporal variable, envp, and call execve()
Lets say program A sits here: /home/a, and program B and BB sits here: /home/a/b
This is my code of program A who sits in /home/a
#include <iostream>
#include <errno.h>
int main() {
int pid;
char *cmd[20] = {"/home/a/b/B", NULL};
if ((pid = fork()) == 0) {
/*if (putenv("PWD=/home/a/b") < 0) {
fprintf(stderr, "error PWD%s\n", strerror(errno));
}*/
char *envp[20] = {"PWD=/home/a/b", NULL};
execve( cmd[0], cmd, envp);
fprintf(stderr, "error: execv: %s\n", strerror(errno));
exit(0);
} else if (pid < 0) {
fprintf(stderr, "error: fork: %s\n", strerror(errno));
exit(0);
}
fprintf(stderr, "father quits\n");
return 0;
}
I tried both of my solutions, but none of them worked,
I mean, I manage to execute program B, but it can't find program BB.
I also printed program's B's PWD, and it's /home/a/b/ - but still, it cannot execute BB.
Is it possible?
Can someone see what I am I do wrong?
Thanks
You are looking for chdir() instead of the envp manipulation.