将 exec 与从键盘键入的命令一起使用

use exec with a command typed from keyboard

我创建了一个字符串数组来将属性放入命令(例如 ls -l),但是 exec 命令需要一个字符数组,我该如何解决?这段代码应该创建一个 child 来执行输入选择的命令。我什至在 pid != 0 时对 wait() 有一些问题。你能帮我完成它吗?非常感谢。

int main(void) {

        char array[100];
        char character;
        int i = 0;
        char* point;
        int j = 0;

        printf ("Digit a string");
        printf ("\n");
        do {
            character = getchar();
            array[i] = character;
            i++;
        }
        while (character != '\n');
        array[i-1] = '[=10=]';
        i = 0;

        char* string[100];

        char *word = strtok(array, " .");
        while (word != NULL) {
            printf("%s\n", word);
            string[j] = word;
            word = strtok(NULL, " .");

        }

        printf ("\n");  

    pid_t  pid;
    pid = fork();

        if (pid == -1) {

        perror("");

    }else if (pid == 0) {

        if (execlp(string, NULL) < 0) {     /* execute the command  */

                    exit(1);
            }
      else {

        //.. wait until the child ends
        wait(pid);



      }
   }
    return;
}

你的大问题是你没有正确使用 execlpexeclp 采用可变数量的参数,这些参数是传递给程序的参数。预计会这样工作:

execlp("ls", "ls", "-l", NULL);

您拥有的是一个参数数组,因此您想使用 exec 的 v 变体之一。您可以找到所有变体 here。所以你想要做的更像这样:

execvp(string[0], string);

请注意,命令本身是两个示例中的参数之一。您的程序的另一个问题是您没有在使用 strtok 的循环中递增 j。另请注意,对于 execvp,数组的最后一个元素应该是 NULL,因此 exec 知道它找到了最后一个参数。最后一件事是您不必检查任何 exec 函数的 return 值。如果 exec returned 那意味着有一个错误,否则它永远不会 returns。 errno 是在 exec 失败时设置的,因此您可以检查一下。为了完整起见,下面的更正代码部分带有注释:

char *word = strtok(array, " .");
j = 0;
while (word != NULL) {
  printf("%s\n", word);
  string[j++] = word; // Increment j
  word = strtok(NULL, " .");
}
string[j] = NULL; // Make sure the array is NULL terminated

还有你打电话的地方exec

execvp(string[0], string); // You most likely want execvp, execv would work as 
                           // well but that takes an entire path and not a filename
fprintf(stderr, "Failed to exec"); // If the program reached this point we know exec failed
exit(1);

让我更详细地解释他在 execvp 发表的评论。名称中带有 pexec 变体采用文件名而不是路径。这些变体将模仿 shell 的工作方式并使用 PATH 环境变量来查找二进制文件。因此,如果您执行 execlp("ls", "ls", "-l", NULL); 之类的操作,假设您在 PATH 指定的文件夹之一中有 ls,它将起作用。如果你做 execl("ls", "ls", "-l", NULL);(不是缺少 p),它将失败,因为 "ls" 不是有效路径;它必须是 "/usr/bin/ls" 之类的东西。你想要哪个版本,需要文件名或文件路径的东西,取决于你的应用程序。