我一直在研究自定义外壳脚本,并在使用下面给出的代码重定向输出时遇到一个小错误。在当前状态下,代码可以正常运行,但是当传递给execvp args时会抛出诸如:(ls“>” no such file or directory)之类的错误。我知道这是因为它将整个args []传递给了不起作用的父外壳。加上args [j] = NULL可消除“ <” /“>”,从而解决错误,但也导致重定向不再起作用。我如何才能不引发错误但又能正常工作?我已经阅读了该问题的多个版本,但似乎找不到答案。预先感谢您的帮助。
switch (fork()){
case -1:
fprintf(stderr, "error forking");
case 0://CHILD
for(int j = 0; j < size; j++){
if(!strcmp(args[j], "<")){//looking for input character
++ext;
if((in = open(args[j+1], O_RDONLY)) < 0){//open file for reading
fprintf(stderr, "error opening file\n");
}
dup2(in, STDIN_FILENO);//duplicate stdin to input file
close(in);//close after use
//args[j] = NULL;
}//end input chech
if(!strcmp(args[j],">")){//looking for output character
++ext;
out = creat(args[j+1], 0644);//create new output file
dup2(out, STDOUT_FILENO);//redirect stdout to file
close(out);//close after usere
// args[j] = NULL;
}//end output check
if(!strcmp(args[j], ">>")){//looking for append
++ext;
int append = open(args[j+1],O_CREAT | O_RDWR | O_APPEND, 0644);
dup2(append, STDOUT_FILENO);
close(append);
// args[j] = NULL;
}
}//end loop
execvp(args[0],args);//execute in parent
fprintf(stderr, "error in child execi \n");//error
exit(0);
default://PARENT
wait(&status); //wait for child to finish
}//end switch
答案 0 :(得分:2)
当您解析重定向(例如<
,>
,>>
)并执行open/dup2
时,您必须将从您传递给execvp
的参数列表。
因此,根据您的args
,您需要一个 second (例如args_clean
)参数列表,您只能在程序名称上复制 它的论点。
而且,您需要额外增加j
来跳过args
中的重定向文件(即,仅执行j + 1
是等效的)。
这是已清理的子代码[请原谅免费的样式清理]:
char *args_clean[size];
int cleanidx = 0;
for (int j = 0; j < size; j++) {
if (!strcmp(args[j], "<")) { // looking for input character
++j;
if ((in = open(args[j], O_RDONLY)) < 0) { // open file for reading
fprintf(stderr, "error opening file\n");
}
dup2(in, STDIN_FILENO); // duplicate stdin to input file
close(in); // close after use
continue;
} // end input chech
if (!strcmp(args[j], ">")) { // looking for output character
++j;
out = creat(args[j], 0644); // create new output file
dup2(out, STDOUT_FILENO); // redirect stdout to file
close(out); // close after usere
continue;
} // end output check
if (!strcmp(args[j], ">>")) { // looking for append
++j;
int append = open(args[j], O_CREAT | O_RDWR | O_APPEND, 0644);
dup2(append, STDOUT_FILENO);
close(append);
continue;
}
args_clean[cleanidx++] = args[j];
} // end loop
args_clean[cleanidx] = NULL;
execvp(args_clean[0], args_clean); // execute in parent
fprintf(stderr, "error in child execi \n"); // error
exit(0);
此外,请在此处查看我的答案,以获取与管道类似的内容:fd leak, custom Shell
对于完整的外壳,请参见我的答案:Implementing input/output redirection in a Linux shell using C,并查看嵌入式的pastebin链接