【发布时间】:2017-02-10 15:28:37
【问题描述】:
我正在编写一个 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);
}
【问题讨论】:
-
通过 strace -f 运行可执行文件以检查它究竟试图生成什么。 execvp 很可能应该是 execvp(args[1], args+1)。
-
在调用`exec之前添加一些调试代码打印出所有
args的元素指向怎么样? -
我得到 args[0] = lsh, args[1] = ls, args[2] = null
-
@penatozawa 您的目标是完全跳过 args[0],这就是 args[1] 和 args+1 的原因。下面的答案解释了到底发生了什么; &args[1] 与 (args + 1) 相同。
-
谢谢你们。这解决了它。