How can I escape variables sent to the 'system' command in C++?

前端 未结 5 1560
迷失自我
迷失自我 2021-01-18 18:19

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=\         


        
相关标签:
5条回答
  • 2021-01-18 18:32

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

    #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. */
    }
    
    0 讨论(0)
  • 2021-01-18 18:34

    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?

    0 讨论(0)
  • 2021-01-18 18:47

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

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

    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).

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

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

    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.

    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))

    Have fun learning all this!

    0 讨论(0)
  • 2021-01-18 18:52

    You could try execl..

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

    #include <unistd.h> 
    
    int execl(const char *path, const char *arg, ...); 
    
    0 讨论(0)
  • 2021-01-18 18:56

    You can use environment variables to safely pass parameters to the comand executed by system(3)

    setenv ("mypar1", "'$(rm -rf /)", 1);
    setenv ("mypar2", "\"; rm -rf /", 1);
    system ("echo mypar1=\"$mypar1\" mypar2=\"$mypar2\");
    

    Neither of these evil codes will be executed, simply printed.

    0 讨论(0)
提交回复
热议问题