I am doing a simple shell program in Linux. I am trying to implement the pipe operator for shell. I cant seem to find the problem and solution. The execvp didnt read from the previous pipe pipi. So if i do ls -l | more, the more prints bad usage instead of the list of files
Here is my code below.
- execCommands handles the commands.
- command.h parse the command.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <wait.h>
#include "modules/token.h"
#include "modules/command.h"
#define BUFSIZE 10000
int tokenSize = 0;
int cmdSize = 0;
char promptSymbol[BUFSIZE] = "%";
char cwd[BUFSIZE];
// execute commands accordingly to the apropriate function
void execCommands(Command command[]){
int fd = 0;
char dir[BUFSIZE];
pid_t pid, p2;
int pipi[2];
for(int i = 0;i < cmdSize;i++){
//start executing commands
if(strcmp(command[i].argv[0], "prompt") == 0){
strcpy(promptSymbol, command[i].argv[1]); //change prompt symbol
}else if(strcmp(command[i].argv[0], "pwd") == 0){
if(getcwd(cwd, sizeof(cwd)) != NULL){
printf("%s\n", cwd );
}else{
perror("getcwd() error\n");
}
}else if(strcmp(command[i].argv[0], "cd") == 0){
if(command[i].argv[1] == NULL){
strcpy(dir, "/home");
}else if(strcmp(command[i].argv[1], "~") == 0 || strcmp(command[i].argv[1], "~/") == 0){
strcpy(dir, "/home");
}else{
strcpy(dir, command[i].argv[1]);
}
if(chdir(dir) < 0){
printf("No such directory/file %s found\n", dir);
}
}else{
pid = fork();
if(pid < 0){
perror("pid fork failed\n");
}
if(pid == 0){
if(command[i].stdin_file || command[i].stdout_file){
//check for stdin redirection
if(command[i].stdin_file){
fd = open(command[i].stdin_file, O_RDONLY);
dup2(fd, STDIN_FILENO);
}
//check for stdout redirection
if(command[i].stdout_file){
fd = open(command[i].stdout_file, O_WRONLY | O_CREAT, 0777);
dup2(fd, STDOUT_FILENO);
}
}
if(strcmp(command[i].sep,"|") == 0){
if(pipe(pipi) == -1){
perror("pipi pipe failed\n");
}
close(pipi[0]);
dup2(pipi[1], STDOUT_FILENO);
close(pipi[1]);
execvp(command[i].argv[0], command[i].argv);
p2 = fork();
if(p2 > 0){
close(pipi[1]);
dup2(pipi[0], STDIN_FILENO);
close(pipi[0]);
execvp(command[i].argv[0], command[i].argv);
}
}else{
execvp(command[i].argv[0], command[i].argv);
}
close(fd);
exit(0);
}else{
if(strcmp(command[i].sep, "&") != 0){
wait(0);
}
} // end of first fork()
} //end of command check
} //end of for loop
} //end of execCommands
//handles SIGINT, SIGTSTP and SIGQUIT
void handler(int num){
printf("\nEnter 'exit' to end shell program\n");
}
main code
int main(){
char cmdLine[BUFSIZE];
char *token[BUFSIZE];
Command command[BUFSIZE];
//Runs untill user wants to exit
while(strcmp(cmdLine, "exit") != 0){
signal(SIGTSTP, handler); //Ignores SIGTSTP signal(ctrl+z)
signal(SIGINT, handler); //Ignores SIGINT signal(ctrl+c)
signal(SIGQUIT, handler); //Ignores SIGQUIT signal(ctrl+\)
//get current directory
if(getcwd(cwd, sizeof(cwd)) != NULL){
strcat(cwd, promptSymbol);
}else{
perror("getcwd error");
return 1;
}
//prompts user for icommand
printf("%s ", cwd);
scanf(" %[^\n]", cmdLine);
// split command line into tokens
tokenSize = tokenise(cmdLine, token);
//split the tokens into commands
initCommand(command);
cmdSize = seperateCommands(token, command);
//execute commands accordingly
execCommands(command);
}
return 0;
}