Can't execute ping from program - c++

I'm trying to execute ping command within my program. I'm working on newest Raspian on RaspBerry Pi B Model. It tells me that:
/bin/sh-c: 0: Can't open ping -c 1 192.168.0.12
My code(it's not finished jet, i know that following code can have some issues):
int status;
pid_t pid;
pid = fork();
const char* commandChar = commandName.c_str();
if(pid == 0)
{
execl(SHELL, SHELL "-c", commandChar, NULL);
_exit(1);
}else if(pid < 0)
{
return false;
}
commandChar = NULL;
delete commandChar;
return true;
Ping (/bin/ping) have rwsr-xr-x permissions, so why I can't execute it and how to make it work?

execl expects a file path, you are giving it the file path "/bin/ping -c 192.168.0.12", which of course doesn't exist. Look at the man page for execl, you will see that the last argument is used for the arguments to the program to be run.

Related

How to get pid of some process started inside child process with help if exec family in C/C++ in linux?

I want to get the pid of some process(let's call it Somebinary) which is started with the help of exec family inside child process and assume Somebinary never stops once started. I want to print the pid of this process from the parent process.
I can't wait in the parent process as the child process will start Somebinary through exec* and that will never stop. I know I can do:
int start(std::string Somebinary){
pid_t childpid = fork();
if(childpid == 0){
freopen(logfile.c_str(), "a+", stdout);
dup2(1, 2);
exec*("/bin/sh", "sh", "-c", Somebinary.c_str(), " &", NULL)
exit(1);
}
// print pid of Somebinary from here
return 0;
}
but I want to reduce extra overhead if possible.
Basically, I want to do the following thing as we do in bash from C/C++:
Bash
$ Somebinary > logfile 2>&1 &
$ pidof Somebinary
I know I can do stdout and stderr redirects with the help of freopen and dup2 in the child process. But the rest is the doubt.
P.S.: this has to be done in Linux
Thanks a lot for the help.
Note that exec does not "create a process" or change the PID, fork does.
As #kaylum said, childpid is the PID of the exec'd process already. You can just print it:
int start(std::string Somebinary){
pid_t childpid = fork();
if(childpid == 0){
freopen(logfile.c_str(), "a+", stdout);
dup2(1, 2);
exec(Somebinary.c_str(), NULL);
exit(1);
}
if (childpid < 0) { // basic error handling
perror("fork"); return -1;
}
// print pid of Somebinary from here
printf("childpid = %jd\n", (intmax_t) childpid);
return 0;
}
Also you might want to bypass /bin/sh and exec the Somebinary directly, otherwise you'll get the PID of /bin/sh.

tar command in execl using busybox. Error: no such file or directory

I have a linux based device that runs c++ code using QT framework. Using QProcess is not an option, since we don't have the QT compiled to support it.
I can't create a tar.gz archive using execl().
It returns -1(fail) and error is "No such file or directory"
Code sample:
std::string applicationPathWithName = "/bin/busybox";
QString dataDirectory("/opt/appl/data/");
QString archiveName = QString("AswLogs.tar.gz");
char* applName;
applName = new char [applicationPathWithName.size() + 1];
strcpy(applName, applicationPathWithName.c_str());
itsFlmFileManagerPtr->writeInFile(eFlmFileTypes_LogFile, data); //This creates logs.txt successfully
pid_t pid = fork();
QString command = QString("tar -czvf %1%2 %3logs.txt").arg(dataDirectory).arg(archiveName).arg(dataDirectory);
if(0 == pid)
{
INFO("Pid is 0");
int execStatus = 0;
execStatus = execl(applName, applName, command.toStdString().c_str(), (char*)NULL);
INFO("Execl is done, execStatus= " << execStatus);
std::string errorStr = strerror(errno);
INFO("Error: " << errorStr);
_exit(EXIT_FAILURE);
}
else if (pid < 0)
{
INFO("Failed to fork");
}
else
{
INFO("pid=" << pid);
int status;
if(wait(&status) == -1)
{
INFO("Wait child error");
}
INFO("Resume from fork");
}
Output:
pid=877
Pid is 0
Execl is done, execStatus= -1
Error: No such file or directory
Resume from fork
Permissions:
logs.txt 666 |
busybox 755
How can I get more error details or what is wrong here?
Edit:
So, after a while, I tried to do just the .tar archive and it worked.
Then I tried just to do the .gz compression and it also worked.
Solution:
So, at least in my case, the solution was to do the tar.gz in two steps(Two processes required):
execl("/bin/busybox", "/bin/busybox", "tar", "-cvf", "/opt/appl/data/logs.tar", "/opt/appl/data/logs.txt", (char*) NULL);
execl("/bin/busybox", "/bin/busybox", "gzip", "/opt/appl/data/logs.tar", (char*) NULL);
I don't know what platform or compiler this is, but it generally isn't possible to pass whole command lines to execl(). If I understanding correctly, you are running something like this:
execl ("/bin/busybox", "/bin/busybox", "tar -czvf blah blah", null);
but in general you need
execl ("/bin/busybox", "/bin/busybox", "tar", "-czvf", "blah", "blah", null);
That is, you need to parse the command line down to its individual arguments. That should be easy enough in the case you described, since you already know what the individual arguments are.
I think the problem is that /bin/busybox starts, but chokes when it tries to interpret "tar -czvf blah blah" as the name of an applet to run.
Incidentally -- and probably not related -- busybox "tar" won't handle gzip compression internally by default, unless you have enabled this feature at build time.

Waiting for system call to finish

I've been tasked to create a program that takes a text file that contains a list of programs as input. It then needs to run valgrind on the programs (one at a time) until valgrind ends or until the program hits a max allotted time. I have the program doing everything I need it to do EXCEPT it isn't waiting for valgrind to finish. The code I'm using has this format:
//code up to this point is working properly
pid_t pid = fork();
if(pid == 0){
string s = "sudo valgrind --*options omitted*" + testPath + " &>" + outPath;
system(s.c_str());
exit(0);
}
//code after here seems to also be working properly
I'm running into an issue where the child just calls the system and moves on without waiting for valgrind to finish. As such I'm guessing that system isn't the right call to use, but I don't know what call I should be making. Can anyone tell me how to get the child to wait for valgrind to finish?
I think that you are looking for fork/execv. Here is an example:
http://www.cs.ecu.edu/karl/4630/spr01/example1.html
An other alternative could be popen.
You can fork and exec your program and then wait for it to finish. See the following example.
pid_t pid = vfork();
if(pid == -1)
{
perror("fork() failed");
return -1;
}
else if(pid == 0)
{
char *args[] = {"/bin/sleep", "5", (char *)0};
execv("/bin/sleep", args);
}
int child_status;
int child_pid = wait(&child_status);
printf("Child %u finished with status %d\n", child_pid, child_status);

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
}

WEXITSTATUS always returns 0

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.