Ejemplo n.º 1
0
void execStages(pipeline thePipeline)
{
    pid_t* children = (pid_t*)malloc(sizeof(pid_t) * thePipeline->length);
    int i;
    clstage cursor = thePipeline->stage;
    int** pipes;
    if(children == NULL)
    {
        perror("malloc");
        return;
    }
    pipes = (int**)malloc(sizeof(int*) * (thePipeline->length - 1));
    if(pipes == NULL)
    {
        if(thePipeline->length - 1 > 1)
        {
            perror("malloc");
            free(children);
            return;
        }
    }
    else
    {
        for(i = 0; i < thePipeline->length - 1; ++i)
        {
            pipes[i] = (int*)malloc(sizeof(int) * 2);
            if(pipes[i] == NULL)
            {
                int j;
                perror("malloc");
                for(j = 0; j <= i; ++j)
                {
                    free(pipes[j]);
                }
                free(pipes);
                free(children);
                return;
            }
        }
    }

    for(i = 0; i < thePipeline->length - 1; ++i)
    {
        if(pipe(pipes[i]) < 0)
        {
            int j;
            perror("pipe");
            for(j = 0; j < thePipeline->length - 1; ++j)
            {
                free(pipes[j]);
            }
            free(pipes);
            free(children);
            return;
        }
    }

    for(i = 0; i < thePipeline->length; ++i)
    {
        int j;
        job_item* theJob = (job_item*)malloc(sizeof(job_item));
        if(theJob == NULL)
        {
            int j;
            perror("malloc");
            for(j = 0; j < thePipeline->length - 1; ++j)
            {
                free(pipes[j]);
            }
            free(pipes);
            free(children);
            return;

        }
        cursor = &(thePipeline->stage[i]);
        if((children[i] = fork()) < 0)
        {
            int j;
            perror("fork");
            free(theJob);
            for(j = 0; j < thePipeline->length - 1; ++j)
            {
                free(pipes[j]);
            }
            free(pipes);
            free(children);
            return;

        }
        else if(children[i] == 0)
        {
            /* do child stuff for this stage, including exec-ing */
            /* if it's not the first child, set it up to read from the
             * pipe before it */
            if(i > 0)
            {
                dup2(pipes[i-1][0], STDIN_FILENO);
            }
            /* otherwise check to make sure not supposed to read from input
             * file */
            else if(cursor->inname != NULL)
            {
                FILE* input = fopen(cursor->inname, "r");
                if(input == NULL)
                {
                    /* may need to be more specific */
                    perror(cursor->inname);
                    exit(-1);
                }
                dup2(fileno(input), STDIN_FILENO);
                fclose(input);
            }
            /* if it's not the last child, set it up to write to the pipe
             * after it */
            if(i < thePipeline->length - 1)
            {
                dup2(pipes[i][1], STDOUT_FILENO);
            }
            /* otherwise check to see if supposed to write to file */
            else if(cursor->outname != NULL)
            {
                FILE* output = fopen(cursor->outname, "w");
                if(output == NULL)
                {
                    /* may need to be more specific */
                    perror(cursor->outname);
                    exit(-1);
                }
                dup2(fileno(output), STDOUT_FILENO);
                fclose(output);
            }
            /* close every pipe */
            for(j = 0; j < thePipeline->length - 1; ++j)
            {
                close(pipes[j][0]);
                close(pipes[j][1]);
            }
            execvp(cursor->argv[0], cursor->argv);
            perror(cursor->argv[0]);
            exit(-1);
        }
        /* do parent stuff for this stage */
        theJob->command = newstr(thePipeline->stage[i].argv[0]);
        theJob->job_status = FOREGROUND;
        theJob->pid = children[i];
        addJobToList(theJob);
        foregroundJobNoWait(theJob);
    }
    for(i = 0; i < thePipeline->length - 1; ++i)
    {
        close(pipes[i][0]);
        close(pipes[i][1]);
    }

    while(areForegroundJobs())
    {
        ;
    }

    for(i = 0; i < thePipeline->length - 1; ++i)
    {
        free(pipes[i]);
    }
    free(pipes);
    free(children);
    return;

}
Ejemplo n.º 2
0
/* This takes a pipeline and either execs it or runs the built-in command */
void runPipeline(pipeline thePipeline)
{
    if(executeCommand(thePipeline) == 0)
    {
        pid_t childPid;
        job_item* theJob;
        int i;
        /* must check every argv */
        int j;
        for(j = 0; j < thePipeline->length; ++j)
        {
            for(i = 1; i < thePipeline->stage[j].argc; ++i)
            {
                if(strcmp(thePipeline->stage[j].argv[i],
                          "&") == 0)
                {
                    /* exec in the background */
                    if(i < thePipeline->stage[j].argc - 1)
                    {
                        fprintf(stderr, "Junk after '&'.\n");
                        return;
                    }
                    if(thePipeline->length > 1)
                    {
                        fprintf(stderr, "Pipelines cannot be backgrounded.\n");
                        return;
                    }
                    if((childPid = fork()) < 0)
                    {
                        perror("fork");
                        return;
                    }
                    else if(childPid == 0)
                    {
                        /* exec it in the background, ignoring the last argv[] */
                        thePipeline->stage->argv[thePipeline->stage->argc - 1]
                            = (char*)0;
                        execvp(thePipeline->stage->argv[0],
                               thePipeline->stage->argv);
                        perror(thePipeline->stage->argv[0]);
                        exit(-1);
                    }
                    /* add the new job to the background */
                    theJob = (job_item*)malloc(sizeof(job_item));
                    if(theJob == NULL)
                    {
                        perror("malloc");
                        return;
                    }
                    theJob->command = newstr(thePipeline->cline);
                    theJob->job_status = BACKGROUND;
                    theJob->pid = childPid;
                    addJobToList(theJob);
                    backgroundJob(theJob);

                    return;
                }
            }
        }
        /* exec the whole pipeline in the foreground */
        execStages(thePipeline);
    }
}
Ejemplo n.º 3
0
int
main(void)
{
  static char buf[100];
  int fd;
  //int status;
  
  // Assumes three file descriptors open.
  while((fd = open("console", O_RDWR)) >= 0){
    if(fd >= 3){
      close(fd);
      break;
    }
  }
  
  // Read and run input commands.
  int jobcntr = 0;
  jlist = malloc(sizeof(*jlist));
  jlist->first = 0;
  jlist->last = 0;
  jlist->fgJob = 0;
  
  int waitStatus;
  int bPrintDollar = 1;
  int cmdLen = 0;
  while((cmdLen = getcmd(buf, sizeof(buf), bPrintDollar)) >= 0){

      clearFinishedJobs(jlist);
	
      // Check if there's a forground job running. 
      // If so - the shell should not function, but only transfer the data received from the console to the job's pipe
      if (jlist->fgJob != 0) {
	  bPrintDollar = 0;
	  write(jlist->fgJob->fd, buf, cmdLen);
	  continue;
      }
      bPrintDollar = 1;
      
      if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') {
	// Clumsy but will have to do for now.
	// Chdir has no effect on the parent if run in the child.
	buf[strlen(buf)-1] = 0;  // chop \n
	if(chdir(buf+3) < 0)
	  printf(2, "cannot cd %s\n", buf+3);
	continue;
      }

      if(buf[0] == 'j' && buf[1] == 'o' && buf[2] == 'b' && buf[3] == 's' && (buf[4] == '\n' || buf[4] == ' ')) {
	  struct job* job = jlist->first;
	  while (job != 0) {
	      printjob(job->jid);
	      job = job->next;
	  }
	  if (!jlist->first)
		  printf(1, "There are no jobs.\n");
	  continue;
      }

      if(buf[0] == 'f' && buf[1] == 'g' && (buf[2] == '\n' || buf[2] == ' ')) {
	  char* c = &buf[3];

	  int jid = atoi(c);

	  struct job* j = jlist->first;
	  while ( j->jid != jid && j != 0) {
	      j = j->next;
	  }
	  jlist->fgJob = j;
	  //fg(jid);
	  continue;
      }

      // 0x0A - new line
      if (buf[0] != 0x0A ) { 
	
	  // create a pipe so the the shell sends the input to jobs_pipe[1] and the new process gets it in jobs_pipe[0]
	  if (pipe(jobs_pipe) == -1) {
	      panic("pipe");
	  }	  
	  
	  struct job* job;
	  job = malloc(sizeof(*job));
	  memset(job, 0, sizeof(*job));
	  job->jid = ++jobcntr;
	  job->fd = jobs_pipe[1];
	  
	  //char* s = job->cmd;
	  //char* t = buf;
	  //int i = sizeof(buf);
	  //while(--i > 0 && *t != '\n' && (*s++ = *t++) != 0) ;
	  //*s = 0;

	  

	  struct cmd* command = parsecmd(buf);
	  int childPid = fork1();
	  if(childPid == 0) {	    
	      close(0);	      
	      dup(jobs_pipe[0]);
	      close(jobs_pipe[1]);
	      if(fork1() == 0)
		  runcmd(command);
	      exit(0);
	  }
	  close(jobs_pipe[0]); // The shell doesn't need the READ end.
	  
	  attachjob(childPid, job); // Attach proc to job (Sys call)
		      
	  // shell writes the input to job_buffer ONLY IF the cmd isn't a backgraound job
	  if (command->type != BACK) {
	      jlist->fgJob = job;
	      bPrintDollar = 0;
	  }
	  
	  addJobToList(jlist, job);
	  
	  wait(&waitStatus);
      }
    }
    exit(0);
}