Reputation: 497
I want to make a shell that can use pipes. When I use this code to run a pipe in my shell even though everything is in a WHILE(1) loop my shell terminates. Why? Is there a problem with the use of the dup
function?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{
int pfds[2];
pipe(pfds);
char *ar1;
const char sp = ' ';
int temp, temp1, temp2, acc;
int i, j;
int t = 0;
char *line=(char *) malloc(1024*sizeof(char));
char *frsarg=(char *) malloc(1024*sizeof(char));
char *firstcmd=(char *) malloc(1024*sizeof(char));
char *seccmd=(char *) malloc(1024*sizeof(char));
char *scmd=(char *) malloc(1024*sizeof(char));
char *secondcmd=(char *) malloc(1024*sizeof(char));
char *secarg=(char *) malloc(1024*sizeof(char));
char *frscmd=(char *) malloc(1024*sizeof(char));
char *cmd1=(char *) malloc(1024*sizeof(char));
char *cmd=(char *) malloc(1024*sizeof(char));
char *cmdf=(char *) malloc(1024*sizeof(char));
char *arg1=(char *) malloc(1024*sizeof(char));
char *allarg=(char *) malloc(1024*sizeof(char));
char *arg2=(char *) malloc(1024*sizeof(char));
char *arg3=(char *) malloc(1024*sizeof(char));
while (1) {
/* Ektypwse to command prompt */
printf("$ ");
fflush(stdout);
fgets(line, 1024, stdin); //Reads the command.
for(i=0;i<1024;i++){
if(line[i]=='\n') //Deletes the "Enter" from the end of the string.
{
line[i]='\0'; //Replace "Enter" with \0.
}
if(line[i] == 'e' && line[i+1] == 'x' && line[i+2] == 'i' && line[i+3] == 't' ) {
exit(1);
}
}
seccmd = strchr(line, '|');
acc = 0;
for(i=0;i<1024;i++){
if(line[i]=='|'){
acc = i;
t=t+1;
} //Finds the second space.
}
/*FIRST COMMAND AND ARGUMENT*/
if(acc != 0 ){
//printf("OKIF\n");
for(j=0;j<acc;j++){
//printf("OKFOR\n");
frscmd[j]= line[j];
}
//printf("FIRST COMMAND %s\n", frscmd);
}
/*FIRST ARG*/
frsarg = strchr(frscmd, sp);
if(frsarg != NULL){
while(isspace(*frsarg)) ++frsarg;
}
for (i=0;i<1024;i++){
if (frsarg[i] == ' '){
frsarg[i] = '\0';
}
}
/*FIRST COMMAND*/
acc = 0;
for(i=0;i<1024;i++){
if(frscmd[i]==' '){
acc = i;
break;
}
}
if(acc != 0 ){
//printf("OKIF\n");
for(j=0;j<acc;j++){
//printf("OKFOR\n");
firstcmd[j]= frscmd[j];
}
}
if(firstcmd != NULL){
while(isspace(*firstcmd)) ++firstcmd;
}
printf("FIRST COMMAND TEST %s TEST\n", firstcmd);
printf("FIRST ARGUMENT TEST %s TEST\n", frsarg);
// firstcmd == "ls" ,frsarg == "-l"
/*SECOND COMMAND AND ARGUMENTS */
//seccmd = " | ws -l
//SECOND COMMAND WITHOUT "|" secondcmd = _wc_-l
secondcmd = strchr(seccmd, sp);
if(secondcmd != NULL){
while(isspace(*secondcmd)) ++secondcmd;
}
//SECCOND COMMAND scmd
acc = 0;
for(i=0;i<1024;i++){
if(secondcmd[i]==' '){
acc = i+1;
}
}
if(acc != 0 ){
for(j=0;j<acc;j++){
scmd[j]= secondcmd[j];
}
}
for (i=0;i<1024;i++){
if (scmd[i] == ' '){
scmd[i] = '\0';
}
}
printf("SECOND COMMAND TEST %s TEST\n", scmd);
//SECOND ARGUMENT secarg
secarg = strchr(secondcmd, sp);
if(secarg != NULL){
while(isspace(*secarg)) ++secarg;
}
printf("SECOND ARGUMENT TEST %s TEST\n", secarg);
//FIRST COMMAND = firstcmd____FIRST ARGUMENT = frsarg_____SECOND COMMAND = scmd_____SECOND ARGUMENT = secarg
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
execlp(firstcmd, firstcmd, frsarg,(char*) NULL);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
execlp(scmd, scmd, secarg,(char*) NULL);
}
return 0;
}
}
Upvotes: 1
Views: 101
Reputation: 13576
Well, this is a very long and complex piece of code, and the logic seems rather ad hoc. It would take me way too long to dissect the whole thing.
I do observe that you fork()
only once, and each branch then calls
execlp()
to run one of the two processes in your pipeline. That leaves
no process continuing to run the shell. So you really need to fork()
twice.
Let's say that the original process is A
. After the first call to
fork()
we have original process A
and child A1
. A
then calls
wait()
to pause until A1
terminates. A1
calls fork()
again and
runs the pipelined commands.
Or something like that. Looking at my code bank, I see the last time I experimented with this stuff was in 2000, and I wasn't doing two subprocesses as you are. But this should be a step in the right direction, anyway.
Upvotes: 1