execvp() ls 没有这样的文件或目录
execvp() ls no such file or directory
我正在编写一个 shell 模拟器,如果用户输入 "lsh ls" 我会 运行 命令 ls
并忽略输入的 "lsh"由用户。所以我正在使用 readline 库来获取输入,然后解析该行。然后我使用 fork() 和 execvp() 来 运行 ls 命令。但是,当我键入 lsh ls
时,我得到以下输出:
lsh: ls: No such file or directory
这是我的代码。我认为它将 ls 视为要搜索的文件,但我不明白为什么要这样做。
int main(){
pid_t id;
char* line;
char **args;
while(1){
line = readline("shell: > ");
if(strcmp(line,"exit") == 0){
break;
}
args = parse(line);
if(strcmp(args[0],"lsh") == 0){
id = fork();
if (id == 0){
if(execvp(args[1],args) < 0){
perro("no such command");
}
}
if(id > 0){
printf("I am the parent process, id %d\n",getppid());
}
}
free(line);
}
}
这是解析行的函数。
#define LSH_TOK_BUFSIZE 64
#define LSH_TOK_DELIM " \t\r\n\a"
char **parse(char *line){
int bufsize = LSH_TOK_BUFSIZE, position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token;
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(line, " \n");
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= bufsize) {
bufsize += LSH_TOK_BUFSIZE;
tokens = realloc(tokens, bufsize * sizeof(char*));
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, LSH_TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
free(tokens);
}
您看到的错误消息来自 ls
,而不是 lsh
。
你实际上有:
char *args[] = { "lsh", "ls", 0 };
execvp(args[1], args);
这意味着您尝试执行 ls
,并且执行成功,但是您告诉 ls
它被称为 lsh
,因为 argv[0]
被设置为 lsh
并请求它列出当前目录中的文件 ls
。因此,当 ls
尝试查找文件时,它失败了,并使用您给它的命令名称 lsh
.
报告错误
你可以试试这个(显示的输出是在 macOS Sierra 上获得的):
$ cp /bin/ls xx97
$ ./xx97 23-ish
xx97: 23-ish: No such file or directory
$ rm xx97
您需要使用:
execvp(argv[1], &argv[1]);
然后你将以正统的方式调用ls
。
我正在编写一个 shell 模拟器,如果用户输入 "lsh ls" 我会 运行 命令 ls
并忽略输入的 "lsh"由用户。所以我正在使用 readline 库来获取输入,然后解析该行。然后我使用 fork() 和 execvp() 来 运行 ls 命令。但是,当我键入 lsh ls
时,我得到以下输出:
lsh: ls: No such file or directory
这是我的代码。我认为它将 ls 视为要搜索的文件,但我不明白为什么要这样做。
int main(){
pid_t id;
char* line;
char **args;
while(1){
line = readline("shell: > ");
if(strcmp(line,"exit") == 0){
break;
}
args = parse(line);
if(strcmp(args[0],"lsh") == 0){
id = fork();
if (id == 0){
if(execvp(args[1],args) < 0){
perro("no such command");
}
}
if(id > 0){
printf("I am the parent process, id %d\n",getppid());
}
}
free(line);
}
}
这是解析行的函数。
#define LSH_TOK_BUFSIZE 64
#define LSH_TOK_DELIM " \t\r\n\a"
char **parse(char *line){
int bufsize = LSH_TOK_BUFSIZE, position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token;
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(line, " \n");
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= bufsize) {
bufsize += LSH_TOK_BUFSIZE;
tokens = realloc(tokens, bufsize * sizeof(char*));
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, LSH_TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
free(tokens);
}
您看到的错误消息来自 ls
,而不是 lsh
。
你实际上有:
char *args[] = { "lsh", "ls", 0 };
execvp(args[1], args);
这意味着您尝试执行 ls
,并且执行成功,但是您告诉 ls
它被称为 lsh
,因为 argv[0]
被设置为 lsh
并请求它列出当前目录中的文件 ls
。因此,当 ls
尝试查找文件时,它失败了,并使用您给它的命令名称 lsh
.
你可以试试这个(显示的输出是在 macOS Sierra 上获得的):
$ cp /bin/ls xx97
$ ./xx97 23-ish
xx97: 23-ish: No such file or directory
$ rm xx97
您需要使用:
execvp(argv[1], &argv[1]);
然后你将以正统的方式调用ls
。