通过C程序运行BASH命令

时间:2017-10-08 13:24:04

标签: c string

我试图通过C程序运行BASH命令,但我正在努力使用execv函数。我真的不知道如何编写该函数的第一个参数。我尝试使用strcat函数追加字符串" / bin /"使用argv选项卡的第一个元素,这是我在运行程序时编写的命令,但它不起作用。我得到了一个"分段错误"。而不是使用我尝试使用strdup的strcat函数,但我不知道如何正确使用它。

任何帮助将不胜感激。我的节目如下。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[], char *envp[]){

char *tab[] = {argv[1],NULL};

if(execve(strcat("/bin/",argv[1]), tab, envp)==-1)
{
    perror("execve");
    return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

4 个答案:

答案 0 :(得分:1)

要从C程序运行shell命令,您应该使用system(3)。 如果你想获得它的标准输出(或给它的标准输入,但不是两者),请使用popen(3)(不要忘记pclose这样的流。)

使用的shell(systempopen)并不完全是bash,而是标准POSIX /bin/sh(与bash非常相似,但有一些限制)

要构建该shell命令(但要注意其中的code injections),您可以使用常见的字符串函数,例如snprintfasprintf

请注意execve(2)在成功时不会返回,并且它不会通过shell运行命令,而是直接执行可执行程序。实际上Unix shells(例如bash/bin/sh)经常使用fork(2)execve(2)waitpid(2)并正在实施globbing 。 BTW system&amp; popen也在fork上使用execve/bin/sh -c

  

strcat("/bin/",argv[1])

非常错误,strcat的第一个参数是覆盖的目标缓冲区(因此不能是字符串文字),并且不要检查buffer overflow

您可能想要编码:

char progbuf[80];
int ln = snprintf(progbuf, sizeof(progbuf), "/bin/%s", argv[1]);

您应该稍后查看ln<(int)sizeof(progbuf)

顺便说一句,你的程序,当你改进它时,不使用Bash;它直接执行一些命令。

  

我尝试使用strdup,但我不知道如何使用它。

在使用任何功能之前,您需要仔细阅读其文档,例如strdup(3)(或在终端中输入man strdup)。

答案 1 :(得分:1)

关于:

if(execve(strcat("/bin/",argv[1]), tab, envp)==-1)  

这不起作用,

  1. 文字&#34; / bin /&#34;在只读内存中,因此无法更改(需要一个足够大的char缓冲区来保存完整的字符串,类似于`char string [100] =&#34; / bin /&#34;;
  2. 建议:

    #include <stdio.h>      // perror()
    #include <stdlib.h>     // exit(), EXIT_FAILURE
    #include <sys/types.h>
    #include <sys/wait.h>   // waitpid()
    
    #include <unistd.h>     // fork(), execvp()
    #include <string.h>     // strlen(), strcpy(), strcat()
    
    int main( int argc, char *argv[], char *env[] )
    {
        (void)argc;
    
        char *tab[] = { argv[1], NULL };
    
        char string[strlen(argv[1]) + strlen( "/bin/" ) +1 ];
        strcpy( string, "/bin/" );
        strcat( string, argv[1] );
    
        int status;
    
        pid_t pid = fork();
        switch( pid )
        {
            case -1:   // fork failed
                perror( "fork failed" );
                exit( EXIT_FAILURE );
                break;
    
            case 0:    // child process
                execve( string, tab, env );   // does not return unless an error
                perror("execve failed");
                exit( EXIT_FAILURE );
                break;
    
            default:
                waitpid( pid, &status, 0 );
                break;
        }
    
    }
    

    警告:建议的代码只隐藏参数:argc而不是正确检查它以确保命令行确实包含参数。

    警告:main的参数:env[]不可移植,不应使用。建议使用:

    extern char *environ[];
    

答案 2 :(得分:0)

Melpomene是对的 - 你不能那样使用strcat。在C中,您无法返回字符串。你要做的是将一个内存地址(指针)作为strcat中的第一个参数传递,然后strcat修改它所指向的内存,以便它还包含strcat的第二个参数。这是一个你将在C中反复重复的过程,所以你应该理解它。此外,strcat看起来并不安全,我打赌有一个strcatn函数或类似的东西。

答案 3 :(得分:0)

我终于找到了一种方法来做我想做的事情。感谢你们所有人的帮助和帮助。建议!这是解决方案!

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[], char *envp[]){

char *tab[] = {argv[1],argv[2],NULL};

char test[20] = "/bin/";

if(execve(strcat(test,argv[1]), tab, envp)==-1)
{
    perror("execve");
    return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}