如何在C ++中转义发送到'system'命令的变量?

时间:2022-09-06 08:12:23

This question talks about using the system command and passing variables. Here is an example it gives:

这个问题讨论了使用系统命令和传递变量。这是一个例子:

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

One of the comments mentions that if line was passed and contained foo & fire_nukes.exe & REM then it's quite possible something bad could happen.

其中一条评论提到如果行传递并包含foo&fire_nukes.exe和REM,那么很可能发生一些不好的事情。

PHP has a great function called escape_shell_args which can be used to escape parameters that are being passed to the program. Does C++ have a way to do that?

PHP有一个很棒的函数叫做escape_shell_args,它可以用来转义传递给程序的参数。 C ++有办法做到这一点吗?

4 个解决方案

#1


4  

The best way is not to use system() at all. Use fork() and exec() and friends. Here's an example:

最好的方法是根本不使用system()。使用fork()和exec()以及朋友。这是一个例子:

#include <string>
#include <unistd.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <cstdlib>

int fork_curl(char *line)
{
    std::string linearg("line=");
    linearg += line;

    int pid = fork();
    if(pid != 0) {
        /* We're in the parent process, return the child's pid. */
        return pid;
    }
    /* Otherwise, we're in the child process, so let's exec curl. */

    execlp("curl", "-b", "cookie.txt", "-d", linearg.c_str());  
    /* exec is not supposed to return, so something
       must have gone wrong. */
    exit(100);
    /* Note: You should probably use an exit  status
       that doesn't collide with these used by curl, if possible. */
}

int main(int argc, char* argv[])
{
    int cpid = fork_curl("test");
    if(cpid == -1) {
        /* Failed to fork */
        error(1, errno, "Fork failed");
        return 1;
    }

    /* Optionally, wait for the child to exit and get
       the exit status. */
    int status;
    waitpid(cpid, &status, 0);
    if(! WIFEXITED(status)) {
        error(1, 0, "The child was killed or segfaulted or something\n");
    }

    status = WEXITSTATUS(status);
    /* Status now contains the exit status of the child process. */
}

#2


4  

Never pass user input into a system call. Ever.

切勿将用户输入传递给系统调用。永远。

You can try to escape all the characters that you think are dangerous, but you will get it wrong.

你可以尝试逃避你认为危险的所有角色,但你会弄错。

Instead, go at it from the other direction: let the user provide any of a selection of inputs that you define, then do a switch and build your own system call from scratch.

相反,从另一个方向继续:让用户提供您定义的任何选择,然后进行切换并从头开始构建您自己的系统调用。

Admittedly this gets a little tricky when the input to the command-line application to invoke is freeform but, well, that's what actual libraries are for. libcurl, anyone?

不可否认,当要调用的命令行应用程序的输入是*形式时,这有点棘手,但是,这就是实际库的用途。 libcurl,有人吗?

#3


0  

You could try execl..

你可以试试execl ..

http://linux.about.com/library/cmd/blcmdl3_execvp.htm

#include <unistd.h> 

int execl(const char *path, const char *arg, ...); 

#4


0  

See the man page listing all syscalls (system calls are not the system(3) function which forks a shell).

请参阅列出所有系统调用的手册页(系统调用不是分支shell的system(3)函数)。

Read more about system calls and linux kernel, and the overall organization of operating systems

阅读有关系统调用和Linux内核以及操作系统整体组织的更多信息

Back to your question, you could quote for the shell (just follow the shell escape rules to transform your strings; for example prefix any non-letter character with a backslash).

回到你的问题,你可以引用shell(只需遵循shell转义规则来转换你的字符串;例如,用反斜杠作为前缀任何非字母字符)。

See also the man pages of fork, execve, etc.

另请参见fork,execve等的手册页。

Read a good book on advanced linux programming and the famous Advanced Unix Programming

阅读一本关于高级linux编程和着名的高级Unix编程的好书

Use the freedom of most of the software on a Linux distribution. For example, you could study the source code of a simple shell like sash.

使用Linux发行版上大多数软件的*。例如,您可以研究像sash这样的简单shell的源代码。

And perhaps you just want to use curl. Then the best way is to code for the libcurl library (without any call to system(3))

也许你只想使用卷曲。那么最好的方法是编写libcurl库(不需要调用system(3))

Have fun learning all this!

学习这一切,玩得开心!

#1


4  

The best way is not to use system() at all. Use fork() and exec() and friends. Here's an example:

最好的方法是根本不使用system()。使用fork()和exec()以及朋友。这是一个例子:

#include <string>
#include <unistd.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <cstdlib>

int fork_curl(char *line)
{
    std::string linearg("line=");
    linearg += line;

    int pid = fork();
    if(pid != 0) {
        /* We're in the parent process, return the child's pid. */
        return pid;
    }
    /* Otherwise, we're in the child process, so let's exec curl. */

    execlp("curl", "-b", "cookie.txt", "-d", linearg.c_str());  
    /* exec is not supposed to return, so something
       must have gone wrong. */
    exit(100);
    /* Note: You should probably use an exit  status
       that doesn't collide with these used by curl, if possible. */
}

int main(int argc, char* argv[])
{
    int cpid = fork_curl("test");
    if(cpid == -1) {
        /* Failed to fork */
        error(1, errno, "Fork failed");
        return 1;
    }

    /* Optionally, wait for the child to exit and get
       the exit status. */
    int status;
    waitpid(cpid, &status, 0);
    if(! WIFEXITED(status)) {
        error(1, 0, "The child was killed or segfaulted or something\n");
    }

    status = WEXITSTATUS(status);
    /* Status now contains the exit status of the child process. */
}

#2


4  

Never pass user input into a system call. Ever.

切勿将用户输入传递给系统调用。永远。

You can try to escape all the characters that you think are dangerous, but you will get it wrong.

你可以尝试逃避你认为危险的所有角色,但你会弄错。

Instead, go at it from the other direction: let the user provide any of a selection of inputs that you define, then do a switch and build your own system call from scratch.

相反,从另一个方向继续:让用户提供您定义的任何选择,然后进行切换并从头开始构建您自己的系统调用。

Admittedly this gets a little tricky when the input to the command-line application to invoke is freeform but, well, that's what actual libraries are for. libcurl, anyone?

不可否认,当要调用的命令行应用程序的输入是*形式时,这有点棘手,但是,这就是实际库的用途。 libcurl,有人吗?

#3


0  

You could try execl..

你可以试试execl ..

http://linux.about.com/library/cmd/blcmdl3_execvp.htm

#include <unistd.h> 

int execl(const char *path, const char *arg, ...); 

#4


0  

See the man page listing all syscalls (system calls are not the system(3) function which forks a shell).

请参阅列出所有系统调用的手册页(系统调用不是分支shell的system(3)函数)。

Read more about system calls and linux kernel, and the overall organization of operating systems

阅读有关系统调用和Linux内核以及操作系统整体组织的更多信息

Back to your question, you could quote for the shell (just follow the shell escape rules to transform your strings; for example prefix any non-letter character with a backslash).

回到你的问题,你可以引用shell(只需遵循shell转义规则来转换你的字符串;例如,用反斜杠作为前缀任何非字母字符)。

See also the man pages of fork, execve, etc.

另请参见fork,execve等的手册页。

Read a good book on advanced linux programming and the famous Advanced Unix Programming

阅读一本关于高级linux编程和着名的高级Unix编程的好书

Use the freedom of most of the software on a Linux distribution. For example, you could study the source code of a simple shell like sash.

使用Linux发行版上大多数软件的*。例如,您可以研究像sash这样的简单shell的源代码。

And perhaps you just want to use curl. Then the best way is to code for the libcurl library (without any call to system(3))

也许你只想使用卷曲。那么最好的方法是编写libcurl库(不需要调用system(3))

Have fun learning all this!

学习这一切,玩得开心!