嗨,我在我的操作系统签名中为 UNIX 构建了一个小 minishell,当我编译代码并在我的机器上尝试它时没有错误,但是在自动更正器检查代码的那一刻,它会抛出一个 BROKEN PIPE 错误。这就是我所做的:
int main(void)
{
descriptorEntrada = dup(STDIN_FILENO);
descriptorSalida = dup(STDOUT_FILENO);
descriptorError = dup(STDERR_FILENO);
char ***argvv = NULL;
int argvc;
//char **argv = NULL;
//int argc;
char *filev[3] = {NULL, NULL, NULL};
int bg;
int ret;
int status;
pid_t pid;
int i, fd[2], entrada, fd1; //fdOut, fd1, saved_stdout; //fdOut;
setbuf(stdout, NULL); /* Unbuffered */
setbuf(stdin, NULL);
mypid=getpid();
while (1)
{
fprintf(stderr, "%s", "msh> "); /* Prompt */
setSignal();
restoreDescriptors();
ret = obtain_order(&argvv, filev, &bg); //external parser (arguments, in/out/err redirect, background)
if (ret == 0)
break; /* EOF */
if (ret == -1)
continue; /* Syntax error */
argvc = ret - 1; /* Line */
if (argvc == 0)
continue; /* Empty line */
if (argvv[1]==NULL){
if(strcmp(argvv[0][0],"exit")==0){
exit (0);
}
ejecutarComando(argvv,bg,filev);
}
else{
entrada = STDIN_FILENO;
if (filev[0]!=NULL){
entrada=open(filev[0], O_RDONLY);
if(entrada<0){
perror ("Error al abrir el fichero de entrada!\n");
exit(1);
}
}
for(i=0;i<argvc-1;i++){
pipe(fd);
generarProceso(argvv[i], entrada, fd[1]); //fd[1] escritor del pipe
if (entrada!=STDIN_FILENO){
close(entrada);
}
close(fd[1]);
entrada=fd[0]; //el siguiente hijo lee de aqui
}
//ultimo paso
switch (pid=fork()){
case -1:
perror("Error en el fork().\n");
break;
case 0: //hijo
if(entrada!=STDIN_FILENO){
dup2(entrada,STDIN_FILENO);
close(entrada);
}
if(filev[1]!=NULL){ //redirigimos la salida estandar
fd1 = creat(filev[1],0666);
if (fd1<0){
perror("Error al abrir el archivo\n");
break;
}
dup2(fd1,STDOUT_FILENO);
close(fd1);
}
execvp(argvv[i][0],argvv[i]);
default: //padre
if(waitpid(pid,&status,0)>0)
WEXITSTATUS(status);
else{
perror("Error en la ejecucion.\n");
break;
}
}
close(entrada);
}
} //end while
return 0;
}
void setSignal(){
// SHELL SIGNAL CONTROL////
signal(SIGINT,SIG_IGN); //ignoramos SIGINT
signal(SIGQUIT,SIG_IGN); //ignoramos SIGQUIT
signal(SIGKILL, SIG_IGN); //ignoramos SIGKILL
}
void restoreDescriptors(){
dup2(descriptorSalida,STDIN_FILENO);
dup2(descriptorSalida, STDOUT_FILENO);
dup2(descriptorError,STDERR_FILENO);
}
int ejecutarComando(char *** argvv, int bg, char** filev){
pid_t pid;
int status;
int fdIn, fdErr, fdOut;
if (bg==0){ //Si el proceso es en foreground hay que manejar signals
signal(SIGINT,SIG_DFL);
signal(SIGQUIT,SIG_DFL);
signal(SIGKILL,SIG_DFL);
}
if (filev[0] != NULL){
fdIn = open(filev[0], O_RDONLY);
if (fdIn < 0)
{
perror("Error al abrir el fichero de entrada!\n");
return 1;
}
dup2(fdIn, STDIN_FILENO);
close(fdIn);
}
if (filev[1] != NULL){
fdOut = creat(filev[1], 0666);
if (fdOut < 0){
perror("Error al abrir el fichero de salida!\n");
return 1;
}
dup2(fdOut,1);
close(fdOut);
}
if (filev[2] != NULL)
{
fdErr = creat(filev[2], 0666);
if (fdErr < 0)
{
perror("Error al abrir el fichero de error!\n");
return 1;
}
dup2(fdErr, STDERR_FILENO);
close(fdErr);
}
if (strcmp(argvv[0][0], "cd") == 0)
{
cambiarDirectorio(argvv);
return 1;
}
else if (strcmp(argvv[0][0], "umask") == 0)
{
cambiarUmask(argvv);
return 1;
}
else if (strcmp(argvv[0][0], "limit") == 0)
{
limiteRecursos(argvv);
return 1;
}
else if (strcmp(argvv[0][0], "set") == 0)
{
setVariable(argvv);
return 1;
}
else
{
switch(pid=fork()){
case -1:perror("Error en el fork.\n");
case 0: execvp(argvv[0][0], argvv[0]);
perror("Error al ejecutar el mandato.|n");
return 1;
default:
if (bg==0) //FOREGROUND
while(wait(&status)!=pid); //padre espera al hijo
else{ //Background
bgpid = getpid();
printf("%d\n",bgpid);
}
}
}
return 0;
}
ejecutarComando 之后的主要部分似乎运作良好,提前感谢您,并为我糟糕的英语感到抱歉。