usage of system function in cpp program - c++

Please explain the syntax of:
system(const char *command);
I want to use this function for running the command on unix sytem.
I need to execute(automate) several test cases with the same command but,they also have other input values which are different.how do I reuse this code for all the test-cases.

int main()
{
char *base = "./your_testcase " ;
char aux[50] = "./your_testcase " ;
char *args[] = {"arg1" ,"arg2" ,"arg3"};
int nargs = 3;
for(i=0;i < nargs;i++)
{
/* Add arg to the end of the command */
strcat(aux,args[i]) ;
/* Call command with parameter */
system(aux);
/* Reset aux to just the system call with no parameters */
strcpy(aux,base);
}
}

Keep in mind that calling system is the same as calling fork and execl. That mean you need to be aware of things like open socket descriptors and file descriptors. I once had a problem with a TCP/IP socket dying on a server because a client was calling system which created a new socket connection to the server that was not being serviced.

I don't see how the syntax can be a problem:
system( "foo" );
executes the program called foo, via your preferred shell.

Generate a command line for each invokation, then pass those command lines into system() one a time.

See also the question:
'How to call an external program with parameters?;
How to call an external program with parameters?

I would avoid use of the system() function, here is a link to why this might be a bad idea

Here is the code, how to implement system() command in c++
#include <cstdlib>
 
int main()
{
    system("pause");
    return 0;
}

system(const char *command)
Is used to execute a command on the command line of the current operating system. It is generally not the best idea to use this because the commands are platform specific. Keep in mind that const char *command is a string and you can pass any string value as a parameter and it will be sent to the command line.

i think Anter is interested in a example:
for instance to remove a file in a directory:
system("/bin/rm -rf /home/ederek/file.txt");

Related

Can I change the binding of RET in gdb?

I'd like to disable the gdb behavior where typing a carriage return repeats execution of the last command entered. I'd just like it to do nothing. Is this possible?
It seems that repeating most commmands is a default gdb's behavior and there is no setting to change it. This is how it looks in gdb's source:
/* Handle a complete line of input. This is called by the callback
mechanism within the readline library. Deal with incomplete
commands as well, by saving the partial input in a global
buffer. */
static void
command_line_handler (char *rl)
{
...
int repeat = (instream == stdin);
So as you can see repeat is assigned 1 if instream is STDIN. There is no other way to assign repeat a different value.
So what you can do is to build your own gdb executable on your machine from gdb`s source (http://ftp.gnu.org/gnu/gdb/). But before building change a little the line 591 in gdb/event-top.c. Instead of
int repeat = (instream == stdin);
write
int repeat = 0;
One possible trick that might work -- I didn't try it -- would be to use Python to set the prompt callback to invoke "dont-repeat".
It seems like a reasonable feature request to me that gdb have a setting to disable command repetition.

pidof from a background script for another background process

I wrote a c++ program to check if a process is running or not . this process is independently launched at background . my program works fine when I run it on foreground but when I time schedule it, it do not work .
int PID= ReadCommanOutput("pidof /root/test/testProg1"); /// also tested with pidof -m
I made a script in /etc/cron.d/myscript to time schedule it as follows :-
45 15 * * * root /root/ProgramMonitor/./testBkg > /root/ProgramMonitor/OutPut.txt
what could be the reason for this ?
string ReadCommanOutput(string command)
{
string output="";
int its=system((command+" > /root/ProgramMonitor/macinfo.txt").c_str());
if(its==0)
{
ifstream reader1("/root/ProgramMonitor/macinfo.txt",fstream::in);
if(!reader1.fail())
{
while(!reader1.eof())
{
string line;
getline(reader1,line);
if(reader1.fail())// for last read
break;
if(!line.empty())
{
stringstream ss(line.c_str());
ss>>output;
cout<<command<<" output = ["<<output<<"]"<<endl;
break;
}
}
reader1.close();
remove("/root/ProgramMonitor/macinfo.txt");
}
else
cout<<"/root/ProgramMonitor/macinfo.txt not found !"<<endl;
}
else
cout<<"ERROR: code = "<<its<<endl;
return output;
}
its output coming as "ERROR: code = 256"
thanks in advacee .
If you really wanted to pipe(2), fork(2), execve(2) then read the output of a pidof command, you should at least use popen(3) since ReadCommandOutput is not in the Posix API; at the very least
pid_t thepid = 0;
FILE* fpidof = popen("pidof /root/test/testProg1");
if (fpidof) {
int p=0;
if (fscanf(fpidof, "%d", &p)>0 && p>0)
thepid = (pid_t)p;
pclose(fpidof);
}
BTW, you did not specify what should happen if several processes (or none) are running the testProg1....; you also need to check the result of pclose
But you don't need to; actually you'll want to build, perhaps using snprintf, the pidof command (and you should be scared of code injection into that command, so quote arguments appropriately). You could simply find your command by accessing the proc(5) file system: you would opendir(3) on "/proc/", then loop on readdir(3) and for every entry which has a numerical name like 1234 (starts with a digit) readlink(2) its exe entry like e.g. /proc/1234/exe ...). Don't forget the closedir and test every syscall.
Please read Advanced Linux Programming
Notice that libraries like Poco or toolkits like Qt (which has a layer QCore without any GUI, and providing QProcess ....) could be useful to you.
As to why your pidof is failing, we can't guess (perhaps a permission issue, or perhaps there is no more any process like you want). Try to run it as root in another terminal at least. Test its exit code, and display both its stdout & stderr at least for debugging purposes.
Also, a better way (assuming that testProg1 is some kind of a server application, to be run in at most one single process) might be to define different conventions. Your testProg1 might start by writing its own pid into /var/run/testProg1.pid and your current application might then read the pid from that file and check, with kill(2) and a 0 signal number, that the process is still existing.
BTW, you could also improve your crontab(5) entry. You could make it run some shell script which uses logger(1) and (for debugging) runs pidof with its output redirected elsewhere. You might also read the mail perhaps sent to root by cron.
Finally I solved this problem by using su command
I have used
ReadCommanOutput("su -c 'pidof /root/test/testProg1' - root");
insteadof
ReadCommanOutput("pidof /root/test/testProg1");

Executing a command shell from popen and set other command shell

I'm working in a project with a quadrotor and mavlink. I have successfully installed mavproxy in my Ubuntu PC and and ran it without problems from terminal. When I run mavproxy.py from the terminal and connected a quadrotor with support for mavlink (APM autopilot), mavproxy detects the quadrotor and everything is ok.
When you execute mavproxy.py the program in the terminal begin to send and receive several parameters. You can write in the terminal some parameter to access for any configuration. For example, the command help in the terminal:
$ mavlink.py
.
.data beging
.
STABILIZE> "when the program finish the configuration, allowed to you for doing an input any parameter, for example help"
STABILIZE>help
show all helps.
I have a code to execute mavlink.py from C++
include <iostream>
include <stdio.h>
using namespace std;
int main() {
FILE *in;
char buff[512];
if(!(in = popen("mavlink.py", "r"))){
return 1;
}
while(fgets(buff, sizeof(buff), in)!=NULL){
cout << buff;
}
pclose(in);
return 0;
}
When I run this C++ program the terminal shows the same things that would appear if I were running mavproxy.py from the terminal, but I don´t know how can I send a command such as help in the C++ code.
If you read the program, the while statement allows me to capture the parameters generated from the program mavproxy.py and cout in the terminal, but mavlink.py never ends until you write something in the terminal exit or press CTRL + C so the while loop never ends.
I have been reading about the Popen function, but I haven't found the correct form to do this.
I know that I can use the mavlink.h library in my program and send parameters to the quadrotor, but don't want do this with mavlink.h.
I am not sure I understand your question, but I think you want to send commands to mavlink.py as well as read its output.
If that is the case, you must change the open mode of popen() from "r" to "w" so you can write, then you can send commands to it like this:
FILE *fp;
char *command="HELP";
if(!(fp = popen("mavlink.py", "w"))){
return 1;
fwrite(command, sizeof(char), strlen(command), fp);

Problems passing source command to bash from c++ application

I am developing an application for work that allows the users to quickly set environment variables on a terminal basis. By setting the path in each terminal we ensure files with the same name in different directories aren't causing application testing to be problematic. I am Using Qt to build the program which is c++ based and all the datatypes are foundationally the same.
I am using the following code to invoke commands in the terminal from which the application launches from using system(). I can run commands into the bash just fine with code; however, I run into a problem when I attempt to use a command with arguments. This is probably why source doesn't seem to work right as the source command is followed by the filename. It would appear that I drop the argument appended after the bash command.
My Code:
void assignTerminalToPath(QString path)
{
QString data = "";
QString currentUsersHomeDirectory = QDir::homePath();
QString tmpScriptLocation = currentUsersHomeDirectory;
QByteArray ba;
tmpScriptLocation += "/.tmpSourceFile";
QFile tmpSourceFile(tmpScriptLocation);
if(tmpSourceFile.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream output(&tmpSourceFile);
data.append("export PATH=.:");
data.append(path);
data.append(":$PATH");
output << QString("#!/bin/bash\n");
output << data;
tmpSourceFile.close();
}
data.clear();
data.append("/bin/bash -c source ");
data.append(tmpScriptLocation);
ba = data.toLatin1();
const char *cStr = ba.data();
system(cStr);
}
Perhaps I'm not referencing bash correctly and I need something outside of -c?
Reference Execute shell/bash command using C/C++
Thanks for any help in advance!
source is not a program that you can call, it is embedded bash command. It is designed to be processed by bash without invoking another copy of bash, such that environment variables can be changed in current bash copy.
However, you cannot call source as part of system(). And even if you did succeed at that, its effects to change environment variables would be completely lost for caller app once system() has returned.
Try a command to envelop with parameters in double quotes ("command - arg1 - to arg2") to transfer in the function system().
used:
char *com = "\"command -arg1 -arg2\"";
system(com);

C++: How to escape user input for safe system calls?

On a Linux platform, I have C++ code that goes like this:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
std::string command;
command = "mkdir " + myDir;
if (system(command.c_str()) != 0) {
return 1;
}
// continue....
Is passing user input to a system() call safe at all?
Should the user input be escaped / sanitized?
How?
How could the above code be exploited for malicious purposes?
Thanks.
Just don't use system. Prefer execl.
execl ("/bin/mkdir", "mkdir", myDir, (char *)0);
That way, myDir is always passed as a single argument to mkdir, and the shell isn't involved. Note that you need to fork if you use this method.
But if this is not just an example, you should use the mkdir C function:
mkdir(myDir, someMode);
Using system() call with command line parameters without sanitizing the input can be highly insecure.
The potential security threat could be a user passing the following as directory name
somedir ; rm -rf /
To prevent this , use a mixture of the following
use getopt to ensure your input is
sanitized
sanitize the input
use execl instead of system to execute
the command
The best option would be to use all three
Further to Matthew's answer, don't spawn a shell process unless you absolutely need it. If you use a fork/execl combination, individual parameters will never be parsed so don't need to be escaped. Beware of null characters however which will still prematurely terminate the parameter (this is not a security problem in some cases).
I assume mkdir is just an example, as mkdir can trivially be called from C++ much more easily than these subprocess suggestions.
Reviving this ancient question as I ran into the same problem and the top answers, based on fork() + execl(), weren't working for me. (They create a separate process, whereas I wanted to use async to launch the command in a thread and have the system call stay in-process to share state more easily.) So I'll give an alternative solution.
It's not usually safe to pass user input as-is, especially if the utility is designed to be sudo'd; in order to sanitize it, instead of composing the string to be executed yourself, use environment variables, which the shell has built-in escape mechanisms for.
For your example:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
setenv("MY_DIR", myDir, 1);
if (system("mkdir \"${MY_DIR}\"") != 0) {
return 1;
}
// continue....