我正在尝试将用户输入的参数传递给execvp()
。
到目前为止,我已经拆分了字符串。如果用户键入ls -a
,则temp
保存为“ls”,“ - a”后跟NULL字符。我不太确定如何在execvp
中正确指出这一点。在示例中,我使用execvp(temp[position], temp)
看到了它。我知道我现在尝试这样做的方式是错误的,但我不确定如何正确地做到这一点!目前我遇到了分段错误。
int main(int argc, char *argv[])
{
char line[124];
int size = 124;
char *temp = NULL;
while(fgets(line, size, stdin) != NULL ) {
if (strcmp(line, "exit\n") == 0) {
exit(EXIT_SUCCESS);
}
temp = strtok(line, " ");
while (temp != NULL) {
printf("%s\n", temp);
temp = strtok(NULL, " ");
}
execvp(temp, &temp);
}
return EXIT_SUCCESS;
}
答案 0 :(得分:7)
你的问题是temp
是一个单指针,你需要将一个指针数组传递给execvp()
。
类似的东西:
enum { MAX_ARGS = 64 };
char *args[MAX_ARGS];
char **next = args;
temp = strtok(line, " ");
while (temp != NULL)
{
*next++ = temp;
printf("%s\n", temp);
temp = strtok(NULL, " ");
}
*next = NULL;
execvp(args[0], args);
请注意,参数列表已被赋予空指针作为终结符,就像argv[argc] == NULL
中的main()
一样。很明显,我对错误检查不屑一顾(如果你传递超过63个参数,你将会溢出args
数组)。但这包含了核心思想。
通过这个例子,我似乎无法使
ls
的简单命令工作,我尝试了mkdir
和echo
,它们似乎工作正常。传递ls
会从execvp()
返回-1。
我不确定问题可能是什么 - 所有这些对我有用:
ls
ls -l
ls -l madump.c
(其中madump.c
恰好是我正在测试的目录中的文件)我使用的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
char line[1024];
while (fgets(line, sizeof(line), stdin) != NULL)
{
if (strcmp(line, "exit\n") == 0)
exit(EXIT_SUCCESS);
char *args[64];
char **next = args;
char *temp = strtok(line, " \n");
while (temp != NULL)
{
*next++ = temp;
printf("%s\n", temp);
temp = strtok(NULL, " \n");
}
*next = NULL;
puts("Checking:");
for (next = args; *next != 0; next++)
puts(*next);
execvp(args[0], args);
}
return EXIT_SUCCESS;
}
请注意,在创建名称末尾带有换行符的目录后,我将\n
添加到strtok()
令牌列表中。适合讨厌的朋友和令人困惑的半受教育的敌人,但从大多数其他角度来看都是令人讨厌的。请注意我是如何在实际执行之前打印出要传递给execvp()
的数据的。通常,我会使用printf("<<%s>>\n", *next);
而不是puts()
来明确指示参数的开始和结束位置。
运行命令(doit
)的输出是:
$ ./doit
ls -l madump.c
ls
-l
madump.c
Checking:
ls
-l
madump.c
-rw-r--r-- 1 jleffler staff 2352 Jul 28 2011 madump.c
$
你从你的版本得到了什么?
答案 1 :(得分:2)
正如您的代码目前所见,在while(temp != NULL)
完成后,temp
将为NULL!
execvp
期望第一个参数成为文件的路径,该文件将是新的过程映像。 第二个参数应该是一个NULL终止字符串数组,其中该数组的最后一个成员是NULL指针,第一个成员是第一个参数中指定的文件的文件名。
要在代码中实现此功能,请考虑使用以下while
循环:
char **argList = NULL;
unsigned int numArgs = 0;
while (temp != NULL) {
numArgs++;
/* Reallocate space for your argument list */
argList = realloc(argList, numArgs * sizeof(*argList));
/* Copy the current argument */
argList[numArgs - 1] = malloc(strlen(temp) + 1, 1); /* The +1 for length is for the terminating '\0' character */
snprintf(argList[numArgs - 1], strlen(temp) + 1, "%s", temp);
printf("%s\n", temp);
temp = strtok(NULL, " ");
}
/* Store the last NULL pointer */
numArgs++;
argList = realloc(argList, numArgs * sizeof(*argList));
argList[numArgs - 1] = NULL;
/* Finally, pass this to execvp */
execvp(argList[0], argList);
/* If you reach here, execvp() failed */
我上面提供的代码没有进行一些错误检查(例如realloc
或malloc
失败时),但基本上记住这些要点:
请查看the documentation以获得更清晰,更简单的示例。
答案 2 :(得分:1)
我猜这个段错误是因为你传递了一个指向execvp的NULL指针。紧接呼叫之上的循环确保了这一点。
要执行您要执行的操作,您需要为当前名为temp
的内容创建一个字符串指针数组。这将成为您调用的程序的argv
数组。这就是为什么命令通常用作execvp (temp[0], temp)
- argv[0]
通常是程序的名称。
因此,尝试创建一个字符串指针数组,并让每一个都指向line
的标记化单词。您可能需要使用malloc,但如果您想要聪明,您可以直接指向line
。如果你这样做,你需要在每个“单词”之后立即将字符设置为\0
。