Passing Arguments Through system() in C++ - c++

How would I pass a command line variable though a system() command in c++.
I have tried using:
string i;
i = system("./findName.sh");
i += argv[1];
cout << i;
But when i run this it gives me my condition for wrong number of arguments i have written in my shell script.
This is the output I received when running my program with "./findName brandonw". Which is my executable file ran with the argument i want my shell script to run with.
The arguments you put are:
brandonw
usage: findName.sh [only_one_argument]

Just concatenate it to the command string.
string command = "./findName.sh";
command = command + " " + argv[1];
system(command.c_str());

Just rearrange your code a bit:
string i("./findName.sh ");
i += argv[1];
system(i.c_str());
cout << i;
Also note, that system doesn't return a std::string, but an implementation defined int value.
If you need to deal with ./findName.sh's output, you rather need pipe().

Related

Launch C++ program from MATLAB script using MATLAB variables as arguments

I know I can launch a executable in MATLAB with the !example.exe command or system(example.exe) as laid out in this question. However, when I want to pass arguments to the C++ program, anything I type is taken as a string. How can I use MATLAB variables?
For example, let's say example.exe was the following program:
int main(int argc, char *argv[]){
std::cout << argv[1] << std::endl;
}
When I call it from MATLAB as !example.exe hi, I get the output hi.
But what if my MATLAB script were actually:
hi = 'HELLO!';
!example.exe hi
My output is still hi, but I want it to be HELLO!.
How do I do this?
Thanks in advance!
You need to create a string using your variables and then run it using eval. For example:
n = 3;
command = sprintf('!example.exe %i', n);
eval(command)
Don't know if this is what you are looking for, but you can put the execution command together in a string using sprintf and then pass that to system. Something like:
hi = 'Hello!';
command = sprintf('example.exe %s', hi);
system(command);
Just use string concatenation:
hi = 'HELLO!';
system(['example.exe ' hi]);

About fork() while building a shell

here is my code.
pid_t fpid=fork();
if(fpid > 0){
wait(&fpid);
}
else{
do_command();
}
The thing is, the function do_command() only execute one line, so I change the do_command() for this:
else{
execlp("/bin/ls","ls","-al",NULL);
cout<<"\ntest<<endl;
}
Also, the ls command was executed but cout command was missing..
What's wrong with my code?
Please excuse my poor English and help me.
Here is my do_command() function declaration:
void do_command(const char *command) {
//all commands with arguments
const char *kernel_address = "/bin/";
char *kernel_command;
strcpy(kernel_command, kernel_address);
strcat(kernel_command, command);
cout << "\nCommand is:" << kernel_command << "\n" << endl;
execlp(kernel_command, command, NULL);
}
Also, there is no any output while function was called in child process
The next line is not printing because the exec family commands only returns on error. If there is no error, it will replace you program and whatever command intended to be executed in exec, is executed. Therefore cout is not working
From the manual of execlp :
The exec() family of functions replaces the current process image with a new process image.
Once your execlp is called, your program is not running anymore. It has been replaced by ls. Thus, it will never reach the cout

Extracting .rar/.zip using c++

For no particular reason, I'm currently working on a program that extracts .zip/.rar files using system().
I currently have WinRar installed because winrar.exe is able to handle both .zip & .rar files.
int main()
{
vector<wstring> files;
if (ListFiles(L"folder", L"*", files))
{
string program = "\"C:\\Program Files\\WinRAR\\winrar.exe\"";
string args = "x -y";
string type = "*.*";
TCHAR dir[MAX_PATH];
GetCurrentDirectory(MAX_PATH, dir);
wstring current_directory(wstring(L"\"") + dir + wstring(L"\\"));
for (const auto& f : files)
{
if (wcscmp(PathFindExtension(f.c_str()), L".rar") == 0 ||
wcscmp(PathFindExtension(f.c_str()), L".zip") == 0)
{
string file = ws2s(f.c_str());
string output = "\"c:\\Users\\my name\\Desktop\\output\"";
string command = program + " " + args + " " + ws2s(current_directory) + file + "\"" + " " + type + " " + output;
cout << command << endl;
if (system(command.c_str()) != 0)
return GetLastError();
}
}
}
return 0;
}
Because I'm using the command line, and don't want spaces to be a problem I wrap what I can in quotation marks:
-- "C:/users/username/program files (x86)/" --
-- "folder/zipped folder.zip" vs folder/"zipped folder.zip" --
After building the complete command contained in command, I printed it out to the screen so I could Edit->Mark:
"C:\Program Files\WinRAR\winrar.exe" x -y "C:\Users\my name\Documents\Visual Studio 2013\Projects\extractor\folder\unzip.zip" *.* "c:\Users\my name\Desktop\output"
However, 'C:\Program' is not recognized as an internal or external command,
operable program or batch file. is what I'm met with after the system(command) call.
If I Copy & Paste the exact same command into Start->Command Prompt, it works like a dream.
How to extract ZIP files with WinRAR command line?
http://comptb.cects.com/using-the-winrar-command-line-tools-in-windows/
https://www.feralhosting.com/faq/view?question=36
Is there a way different way to invoke the system() call?
If there's not, how else can command line arguments be used?
I'd prefer to [avoid entirely] not use Boost:: or 3rd party libraries.
Thanks!
This is probably because of the quirky behavior of Command Prompt when it comes to quotation of arguments. Whenever you call system("\"arg1\" \"arg2\""), it is equivalent to calling:
cmd.exe /c "arg1" "arg2"
Because of the strange behavior as described in the linked post, this will not be interpreted correctly by Command Prompt. An extra set of quotes is needed:
cmd.exe /c ""arg1" "arg2""
For invoking executables, CreateProcess provides an alternative that gives you more control over the process. You'll still have to quote the arguments but the rules are a bit simpler as the Command Prompt is no longer in your way.

How do I execute a string as a shell script in C++?

I'm writing a program that needs to be able to execute a shell script provided by the user. I've gotten it to execute a single shell command, but the scripts provided will be more complicated than that.
Googling got me as far as the following code snippet:
FILE *pipe;
char str[100];
// The python line here is just an example, this is *not* about executing
// this particular line.
pipe = popen("python -c \"print 5 * 6\" 2>&1", "r");
fgets(str, 100, pipe);
cout << "Output: " << str << endl;
pclose(pipe)
So that this point str has 30 in it. So far so good. But what if the command has carriage returns in it, as a shell script file would, something like the following:
pipe = popen("python -c \"print 5 * 6\"\nbc <<< 5 + 6 2>&1", "r");
With this my goal is that str eventually have 30\n11.
To put another way, assume I have a file with the following contents:
python -c "print 5 * 6"
bc <<< 5 + 6
The argument I'm sending to popen above is the string representation of that file. I want to, from within C++, send that string (or something similar) to bash and have it execute exactly as if I were in the shell and sourced it with . file.sh, but setting the str variable to what I would see in the shell if it were executed there, in this case, 30\n11.
Yes, I could write this to a file and work it that way, but that seems like it should be unnecessary.
I wouldn't think this was a new problem, so either I'm thinking about it in a completely wrong way or there's a library that I simply don't know about that already does this.
use bash -c.
#include <stdio.h>
int main()
{
FILE *pipe = popen("bash -c \"echo asdf\necho 1234\" ", "r");
char ch;
while ((ch = fgetc(pipe)) != EOF)
putchar(ch);
}
Output:
asdf
1234
(I've test on cygwin)

devc++ input from file does not work

I'm trying to redirect a .txt content to .exe
program.exe < file.txt
and contents of file.txt are
35345345345
34543534562
23435635432
35683045342
69849593458
95238942394
28934928341
but the first index in array is the file path and the file contents is not displayed.
int main(int argc, char *args[])
{
for(int c = 0; c<argc; c++){
cout << "Param " << c << ": " << args[c] << "\n";
}
system("PAUSE");
return EXIT_SUCCESS;
}
Desired output:
Param0: 35345345345
Param1: 34543534562
Param2: 23435635432
Param3: 35683045342
Param4: 69849593458
Param5: 95238942394
Param6: 28934928341
The myapp < file.txt syntax passes to stdin (or cin if you prefer), not the arguments.
You have misunderstood what argc and argv are for. They contain the command line arguments to your program. If, for example, you ran:
program.exe something 123
The null terminated strings pointed to by argv will be program.exe, something, and 123.
You are attempting to redirect the contents of a file to program.exe using < file.txt. This is not a command line argument. It simply redirects the contents of the file to the standard input of your program. To get those contents you will need to extract from std::cin.
When you say "but the first index in array is the file path and the file contents is not displayed." it sounds like you're trying to read input from argv and argc. The angle bracket shell operator does not work that way. Instead, stdin (what cin and several C functions read from) has the contents of that file. So, to read from the file in the case above, you'd use cin.
If you instead really wanted to have a file automatically inserted into the argument list, I can't help you with the windows shell. However, if you have the option of using bash, the following will work:
program.exe `cat file.txt`
The backtick operator expands into the result of the command contained within, and so the contents are then passed as arguments to program.exe (again, under the bash shell and not the windows shell)
This code does what i was expecting to do with the other one. Thanks everybody who helped.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string line;
while (getline(cin, line))
cout << "line: " << line << '\n';
}