Aris Kantas
Aris Kantas

Reputation: 497

Why my program terminates (using pipes)?

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

Answers (1)

Tom Zych
Tom Zych

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

Related Questions