【问题标题】:How to Parse a String coming from a Client into an exec()?如何将来自客户端的字符串解析为 exec()?
【发布时间】:2020-06-10 17:17:24
【问题描述】:

我有一个基于管道的客户端-服务器通信,我正在读取用户输入,然后写入管道,将用户输入的内容发送到服务器。然后在服务器上我有这个:

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

    int fd;

    if((fd = open("fifo", O_RDONLY)) < 0){
        perror("open");
        exit(1);
    }

    char buf[100];  
    int bytes_read = 0;

    while((bytes_read = read(fd, buf, 100)) > 0){
        execute_command(buf);
        }
    }
    return 0;
}

所以现在我有了用户在 buf 数组上发送的命令,我调用了具有以下代码的 execute_command 函数:

void execute_command(String command){
     int status;
     pid_t pid;
     char** argv = split(command);

     if( !(pid = fork()) ){
        execlp(argv[0],argv[0],argv + 1);
        _exit(-1);
     }
     else
         wait(NULL);
     }
}

static char** split(char* command){
    int i = 0;
    char** argv = malloc(sizeof(char*) * 100);

    char* c = strtok(command, " ");
    while( c ){
        c = strtok(NULL," "); 
        argv[i++] = strdup(c); 
    }
    argv[i] = 0;

    return argv;
}

运行此程序时,每当我从客户端发送某些内容时,我都会在服务器端收到“分段错误(核心转储)。我认为这是因为我以错误的方式使用了 char 数组和指针。 ..我仍在尝试理解C中所有这些指针的东西。此外,通信需要基于管道,不能像某些人已经告诉我的那样使用套接字。我唯一能真正改变的是声明与字符串相关的变量和 exec() 的类型。

【问题讨论】:

  • 请注意,管道上的消息可能不会以空字节结尾,因此您可能没有使用字符串。
  • 您发布的代码实际上并没有编译,因为 (1) 您没有向我们展示您的 #includes,并且 (2) 您有两个流浪的 }s(一个在 @ 之后) 987654326@ 和wait(NULL); 之后的另一个)。请发布您实际运行的确切代码。
  • 这能回答你的问题吗? strdup dumping core on passing NULL
  • 如果重复的问题本身不是一个足够大的提示,则在split 中循环的最后一次迭代中,cNULL,当您调用strdup(c) 时。

标签: c parsing pipe exec


【解决方案1】:

问题出在execlp(argv[0],argv[0],argv + 1);

execlp 需要一个由char * 参数组成的列表(不是数组),以NULL 结尾,如

    execlp("foo", "bar", "baz", NULL);

您 (1) 将 char ** 作为最后一个参数传递,并且 (2) 在您的参数列表中没有终止 NULL

由于您已经准备了一组参数,请改用execvp

【讨论】:

  • 那么我该如何调用 execvp()? execvp(argv[0], argv+1) ?
  • 不要argv + 1。你调用的程序会被混淆。使用execvp(argv[0], argv)
  • 仍然出现分段错误(核心转储):(
猜你喜欢
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 2019-11-08
  • 1970-01-01
相关资源
最近更新 更多