I've been making a mini shell in C, that has to receive commands with at least 3 arguments, parsing them, then applying fork() and exec(), if you just press enter it should print the prompt back again. Also it has to accept multiple pipes, that's where i have been stuck. This is my code
#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;
Everythig work fine till here.
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;
}
The code works good if I use only 1 command, but when i put a pipe it doesnt get the input,for example:
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:~
Its related to the STDIN_FILE, but also I'm sure I'm not implementing well the pipes and the forks.
Reducing your problem to a minimal reproducible case:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
char *argv[] = {"wc", NULL};
int fd1[2];
pipe(fd1);
dup2(fd1[1],STDIN_FILENO); /* Wrong end of the pipe !! */
close(fd1[1]);
execvp(argv[0], argv);
perror(argv[0]);
return 1;
}
The problem is that fd1[1]
is the write side of a pipe, but wc
is trying to read from it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.