6


  string line;
  ifstream myfile ("aaa.txt");
  getline (myfile,line);
  system("curl.exe -b cookie.txt -d test="+line+"  http://example.com");

And It doesn't work! I also tried line.c_str(); But it didnt work either. Please help me.

Paul R
  • 208,748
  • 37
  • 389
  • 560
martin
  • 71
  • 1
  • 1
  • 4
  • 1
    Downvoted because passing variables to `system()` is **actively dangerous**. Use `spawn()` on Win32, `fork()/exec()` or `posix_spawn()` on *nix. – ninjalj Dec 16 '11 at 20:54
  • 2
    @ninjalj the security of the system has nothing to do with the question. Every time there is a SO question having to do with system(), someone has to comment on security and sometimes people (like you) downvote it. It contributes nothing and only clutters the page. The question was "how" to use system(), not a question on the best ways to use it. "Use something else instead" is not a useful comment. – David Jul 25 '19 at 05:48

3 Answers3

14

It doesn't work because you're passing a C++ string to a C function system(). c_str() can help, but you should apply it to the whole string:

system(("curl.exe -b cookie.txt -d test="+line+"  http://example.com").c_str());

As noted in the comments below, passing random variables to system() can be quite dangerous, so you should only do that if you know exactly what it may contain. If it's supplied by the user or received from the network, you probably shouldn't do that. Pass the string through some sort of "escape" function or use spawn()/exec()/whatever else that doesn't pass it to the shell.

Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73
  • I find it cleaner to add an `int system(std::string const& s) { return s.c_str(); }` overload. – MSalters Feb 08 '11 at 13:07
  • 1
    @MSalters, did you mean `int system(std::string const& s) {return system(s.c_str());}`? Yes, it looks like a good idea. – Sergei Tachenov Feb 08 '11 at 13:28
  • @ninjalj, the question was about _how_ to use variables in such call, not whether it's dangerous or not. In fact, sine the guy reads the variable from a file, not directly from user or network, it isn't necessarily dangerous. That depends on where he got this file. If it's a temporary file generated by the same application and it isn't accessible externally, I guess it's fine. Although I agree that I should have mentioned possible dangers. – Sergei Tachenov Dec 17 '11 at 05:23
  • And now that you've clearly warned about the dangers of system(), I've removed the downvote. Right now, this question has ~350 views, we don't want SO to become a resource on bad practices. – ninjalj Dec 17 '11 at 10:26
11

Problem 1:

Your problem stems from the fact that system is of signature:

int system (const char *command);

What you have is of type std::string.

One way to fix this is to build a new std::string and then get the char pointer using c_str().

string cmd("curl.exe -b cookie.txt -d test=");
cmd += line;
cmd += "  http://example.com";

Then pass the content to system.

system(cmd.c_str());

Problem 2:

Reading data and passing it unvalidated and unclean to system will allow anyone using your program to run commands at the shell.

This is a security risk.

Skurmedel
  • 21,515
  • 5
  • 53
  • 66
  • Aren't `system` cals the same as typing the command in cmd.exe? – Xeo Feb 05 '11 at 16:01
  • 2
    @Xeo: Yup and if you passed `foo & fire_nukes.exe & REM` to his program it would run curl.exe then attempt to run fire_nukes.exe. It would look slightly different on *nix, but the idea is the same. – Skurmedel Feb 05 '11 at 16:07
3

Build the string you're passing to system() with a stringstream!

#include <sstream>
#include <fstream>
#include <string>
using namespace std;

int main(void){
    string line;
    ifstream myfile("aaa.txt");
    getline(myfile,line);
    stringstream call_line;
    call_line << "curl.exe -b cookie.txt -d test=" << line << "  http://example.com");
    system(call_line.str().c_str());
}
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 4
    @ninjalj: So, we know that using `system()` is dangerous if you allow arbitary user input. This doesn't change the fact that the OP wanted to assembly input from a file. What if the file is protected against user access? What if it actually reads from a database or something? We don't know and we don't care, the security is part of the OP's responsibility. This is not a reason for a downvote. I could remove the `system()` call and only show string assembling. What now? – Xeo Dec 16 '11 at 21:08
  • you could tell the OP to use an API where each argument is separate, and doesn't use an underlying shell to parse the command line. – ninjalj Dec 16 '11 at 21:13