将 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;
}
你的大问题是你没有正确使用 execlp
。 execlp
采用可变数量的参数,这些参数是传递给程序的参数。预计会这样工作:
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
发表的评论。名称中带有 p
的 exec
变体采用文件名而不是路径。这些变体将模仿 shell 的工作方式并使用 PATH
环境变量来查找二进制文件。因此,如果您执行 execlp("ls", "ls", "-l", NULL);
之类的操作,假设您在 PATH
指定的文件夹之一中有 ls
,它将起作用。如果你做 execl("ls", "ls", "-l", NULL);
(不是缺少 p
),它将失败,因为 "ls"
不是有效路径;它必须是 "/usr/bin/ls"
之类的东西。你想要哪个版本,需要文件名或文件路径的东西,取决于你的应用程序。
我创建了一个字符串数组来将属性放入命令(例如 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;
}
你的大问题是你没有正确使用 execlp
。 execlp
采用可变数量的参数,这些参数是传递给程序的参数。预计会这样工作:
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
发表的评论。名称中带有 p
的 exec
变体采用文件名而不是路径。这些变体将模仿 shell 的工作方式并使用 PATH
环境变量来查找二进制文件。因此,如果您执行 execlp("ls", "ls", "-l", NULL);
之类的操作,假设您在 PATH
指定的文件夹之一中有 ls
,它将起作用。如果你做 execl("ls", "ls", "-l", NULL);
(不是缺少 p
),它将失败,因为 "ls"
不是有效路径;它必须是 "/usr/bin/ls"
之类的东西。你想要哪个版本,需要文件名或文件路径的东西,取决于你的应用程序。