我有一个从用户接收输入的tokenizer。从那里我继续扫描“>”或“<”潜在的重定向。
for(i=0;i<n;i++){ //I/O redirection
//printf("extracted token is %s\n",tokens[i]);
//get the
if (strcmp(tokens[i],"<")==0) {
printf("found < !!!!\n");
if(tokens[i+1] == NULL){ //if there isn't a input file
printf("Please have a input file\n");
break;
}else if(tokens[i-1] == NULL){ //if there isn't a output file
printf("Pleae have a output file\n");
break;
}
infile = 1;
outfile = 1;
fd=fopen(tokens[i-1],"w");
fclose(fd);
}
}
以上代码只处理“&lt;”重定向。请注意,这只是围绕while循环(shell设计)的一小段代码。在它通过这个for循环后,我有这个:
for(i=0;i<n;i++){
//printf("extracted token is %s\n",tokens[i]);
char *ex = "exit";
char *his = "history";
if(strcmp(tokens[0],his) == 0 && max_cmd == 0 ){ //get history
for(j=0;j<counter;j++){
printf("%i. %s\n",j+1,historic_cmd[j]);
}
}else if(strcmp(tokens[0], his) ==0 && max_cmd == 1){
for(j=0; j<CMD_MAX;j++){
printf("%i. %s\n",j+1,historic_cmd[j]);
}
}else if(strcmp(tokens[0],ex) == 0){ //exit program
exit(2);
}else{ //forking
pid = fork();
if(pid){
pid=wait(NULL);
if(infile > 0)
dup2(fileno(fd),0);
if(outfile > 0)
dup2(fileno(fd),1);
}else{
if(execvp(tokens[0],tokens)){
puts(strerror(errno));
exit(127);
}
}
}
} // end of for loop
}//end of while loop for user input
我很困惑为什么它没有执行重定向。如果我输入以下内容:
ps > s
它在工作目录中创建文件,但它是空的。我错误地使用“dup2”了吗?
“ps&gt; s”的样本输出:
user$>ps > s
ps: illegal option -- >
usage: ps [-AaCcEefhjlMmrSTvwXx] [-O fmt | -o fmt] [-G gid[,gid...]]
[-u]
[-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]]
ps [-L]
ps: illegal option -- >
usage: ps [-AaCcEefhjlMmrSTvwXx] [-O fmt | -o fmt] [-G gid[,gid...]]
[-u]
[-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]]
ps [-L]
ps: illegal option -- >
usage: ps [-AaCcEefhjlMmrSTvwXx] [-O fmt | -o fmt] [-G gid[,gid...]]
[-u]
[-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]]
ps [-L]
found > !!!!!----------------------------------------------------
答案 0 :(得分:0)
您替换父进程的stdin
和stdout
(if(pid)
内),并且不会影响您的孩子。在dup2
之前将else
内容移至execvp
分支。
答案 1 :(得分:0)
这是你应该用来在C中进行重定向的流程。
int file_stdin;
int file_stdout;
int file_stderr;
/*--------------------------------------------------------------------
; code to set infile and outfile I'll assume that if redirection isn't
; being used, the appropriate filehandle will be -1.
;
; file_stdin should be a file that is opened using O_RDONLY.
; file_stdout should be a file that is opened using O_WRONLY.
; file_stdout should be a file that is opened using O_WRONLY.
;
; Be wary of using a file descriptor opened for both reading and writing
; and using the same file descriptor---it will probably not do what you
; expect it to do.
;
; Also note, you can also use file descriptors from the pipe() system
; call (to allow piping from command to command) or network sockets, or
; anything that can be read/written from a file descriptor.
;---------------------------------------------------------------------*/
pid_t child;
child = fork();
if (child < 0)
report_error(errno);
else if (child > 0)
{
int status;
int rc;
/*------------------------------------------------------------------
; wait for the child process. More code needs to be added to
; descriptor errors and what not, but that's left as an exercise for
; the reader
;-----------------------------------------------------------------*/
rc = wait(&status);
}
else
{
/*--------------------------------------------------------------------
; child process. Set up redirection if required. Once the rediretion
; has been set (using dup2()), the original file descriptor is closed
; as it is no longer needed and just wastes file descriptors in the
; child process.
;-------------------------------------------------------------------*/
if (file_stdin > -1)
{
dup2(file_stdin,STDIN_FILENO);
close(file_stdin);
}
if (file_stdout > -1)
{
dup2(file_stdout,STDOUT_FILENO);
close(file_stdout);
}
if (file_stderr > -1)
{
dup2(file_stderr,STDERR_FILENO);
close(file_stderr);
}
/*------------------------------------------------------------------
; close any unneeded open files here ...
;------------------------------------------------------------------*/
/*------------------------------------------------------------------
; PROGRAM, ARGV and ENVP need to be replaced with appropriate values
;------------------------------------------------------------------*/
if(execve(PROGRAM,ARGV,ENVP) < 0)
_exit(EXIT_FAILURE);
}
显然,上面的代码需要适应您的项目,但这是一般流程。