Ich habe eine Mini-Shell in C gemacht, die Befehle mit mindestens 3 Argumente erhalten muss, Parsing sie, dann anwenden fork() und exec(), wenn Sie nur die Eingabetaste drücken Es sollte die Aufforderung erneut drucken. Auch muss es mehrere Rohre akzeptieren, das ist wo ich stecken geblieben bin. Das ist mein CodeShell in C, Eingabe & Pipes
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(){
char command[50];
char* token;
char* param[50][50];
int i,j,k;
while(1){
printf("shell:~");
fgets(command, sizeof(command), stdin);
i=0,j=0;
token = strtok(command," \n\0\t");
while(1){
if(token==NULL) break;
else if(strcmp(token,"|")==0){
param[i][j]=0;
i = i+1;
j=0;
token = strtok(NULL," \n\0\t");
}
else{
param[i][j]=token;
token = strtok(NULL," \n\0\t");
j = j+1;
}
}
param[i][j]=0;
Alles funktioniert gut bis hier.
pid_t pid1,pid2;
int fd1[2],fd2[2];
//int numpipe = i-1;
pipe(fd1);
pipe(fd2);
int status;
pid1 = fork();
if(pid1==0){
k=0;
while(k<i+1){
pid2 = fork();
if(pid2==0){
if(k==0){// if it is first
if(k==i){//and last one
execvp(param[k][0],param[k]);
}else{
dup2(fd1[1],STDOUT_FILENO);
close(fd1[0]);
execvp(param[k][0],param[k]);
}
}else if(0<k<i){//if it is in the middle
if(k%2==0){ // position odd
dup2(fd2[0],STDIN_FILENO);
close(fd2[1]);
dup2(fd1[1],STDOUT_FILENO);
close(fd1[0]);
execvp(param[k][0],param[k]);
}else{ //position
dup2(fd1[0],STDIN_FILENO);
close(fd1[1]);
dup2(fd2[1],STDOUT_FILENO);
close(fd2[0]);
execvp(param[k][0],param[k]);
}
}else{//if it is lasts
if(k%2==0){
dup2(fd2[0],STDIN_FILENO);
close(fd2[1]);
execvp(param[k][0],param[k]);
}else{
dup2(fd1[1],STDIN_FILENO);
close(fd1[1]);
execvp(param[k][0],param[k]);
}
}
}else{
k++;
wait(NULL);
}
}
}
else{
wait(NULL);
}
}
return 0;
}
Der Code funktioniert gut, wenn ich nur 1 Befehl zu verwenden, aber wenn ich ein Rohr setzen tut es den Eingang zu erhalten, zum Beispiel:
shell:~ls -l
total 112
-rw-r--r-- 1 cristian cristian 72018 mar 28 13:25 (107315)proyecto1-SO2017-1.pdf
-rw-rw-r-- 1 cristian cristian 0 abr 2 12:23 a.out
-rw-rw-r-- 1 cristian cristian 1082 abr 1 23:47 reaspaldo2
-rw-rw-r-- 1 cristian cristian 1217 abr 2 03:00 reaspaldo2.c
-rw-rw-r-- 1 cristian cristian 962 abr 1 19:40 respaldo1
-rw-rw-r-- 1 cristian cristian 636 abr 2 01:10 respaldo1.c
-rwxrwxr-x 1 cristian cristian 13200 abr 2 12:35 shell
-rw-r--r-- 1 cristian cristian 1984 abr 2 12:36 shell.c
-rw-r--r-- 1 cristian cristian 807 mar 29 11:41 shell.c~
shell:~ls -l | wc
wc: 'standard input': Bad file descriptor
0 0 0
shell:~
Sein zum STDIN_FILE verwendet, aber auch ich Ich bin mir sicher, dass ich die Rohre und die Gabeln nicht gut umsetzen kann.
Sie schließen nicht alle Ihre Dateideskriptoren. Normalerweise sollte Ihr Code wie folgt aussehen: 'pipe (fd); if (fork() == 0) {schließen (fd [0]); dup2 (fd [1], STDOUT_FILENO); close (fd [1]) ' –
yeah, das habe ich auch schon ausprobiert, aber es tut das gleiche, ist wie die excvp() bekommt nicht die Argumente aus der Pipe –
Fix ein Problem zu einer Zeit. Sie schließen keine Dateideskriptoren im übergeordneten Element überhaupt! Aber das unmittelbare Problem ist 'dup2 (fd1 [1], STDIN_FILENO);'. 'fd [1]' ist die Schreibseite der Pipe und sollte in geschrieben werden. Wenn Sie versuchen, davon zu lesen, wird der angezeigte Fehler generiert. –