Esempio n. 1
0
static void
fork_exec_wait (const char *command)
{
  char buf [255];
  pid_t forked;
  int status;

  switch ((int) (forked = fork ()))
    {
    case -1:
      sprintf (buf, "%s: couldn't fork", progname);
      perror (buf);
      return;

    case 0:
      exec_simple_command (command);
      exit (1);  /* exits child fork */
      break;

    default:
      waitpid (forked, &status, 0);
      break;
    }
}
Esempio n. 2
0
void
execute_command (command_t c, bool time_travel)
{
  int exitStatus;           //use this variable to store return value of call to exec_simple_command
                            //store the value into the command's status data member
  
  switch(c->type)
  {
    // AND, OR, SEQUENCE, and PIPE commands (passed into this function as parameter c)
      // store their arguments in their data member command_t *command[2] (located in the union --> u.command)
      // the way the command tree works, the pointers to commands stored in command[0] and command[1]
      // are simple commands --> to pass them into exec_simple_command, pass in the u.word data member of
      // the simple commands
      //c->(u.command[0])->(u.word)
        
    // AND: only attempt to execute the second argument if the first succeeds    
    case AND_COMMAND:
    {
      if(c->u.command[0]->type == SIMPLE_COMMAND)
      {
        exitStatus = exec_simple_command(c->u.command[0]->u.word, c->u.command[0]);
        c->u.command[0]->status = exitStatus;
      }
      else
      {
        execute_command(c->u.command[0], 0);
        exitStatus = c->u.command[0]->status;
      }
      
      //if the first argument was successfully executed, try to execute the second
      if(exitStatus == 0)
      {
        if(c->u.command[1]->type == SIMPLE_COMMAND)
        {
          exitStatus = exec_simple_command(c->u.command[1]->u.word, c->u.command[1]);
          c->u.command[1]->status = exitStatus;
        }
        else
        {
          execute_command (c->u.command[1], 0);
          exitStatus = c->u.command[1]->status;
        }
      }
      
      //if the first argument of AND failed, immediately set c->status to the fail status
      //if the first argument succeeded, the second argument was executed, and c->status will be the
        //status of the second argument
      c->status = exitStatus;
    }
      break;
      
      
    // OR: only attempt to execute the second argument if the first argument fails
    case OR_COMMAND:
    {
      if(c->u.command[0]->type == SIMPLE_COMMAND)
      {
        exitStatus = exec_simple_command(c->u.command[0]->u.word, c->u.command[0]);
        c->u.command[0]->status = exitStatus;
      }
      else
      {
        execute_command(c->u.command[0], 0);
        exitStatus = c->u.command[0]->status;
      }
      
      
      //if the first argument was unsuccessful, execute the second
      if(exitStatus != 0)
      {
        if(c->u.command[1]->type == SIMPLE_COMMAND)
        {
          //c->u.command[1]->status = exec_simple_command(c->u.command[1]->u.word, c->u.command[1]);
          exitStatus = exec_simple_command(c->u.command[1]->u.word, c->u.command[1]);
          c->u.command[1]->status = exitStatus;
        }
        else
        {
          execute_command (c->u.command[1], 0);
          exitStatus = c->u.command[1]->status;
        }
        
      }
      
      //if the first argument of OR succeeded, immediately set c->status to the success status
      //if the first argument failed, the second argument was executed, and c->status will be the
        //status of the second argument
      c->status = exitStatus;      
    }
      break;

    // SEQUENCE: will always have 2 arguments (decision when implementing in make_command_stream)
    // always execute the second argument even if the first one fails
    // sequence command status will be the status of the second argument
    case SEQUENCE_COMMAND:
    {
      if(c->u.command[0]->type == SIMPLE_COMMAND)
      {
        c->u.command[0]->status = exec_simple_command(c->u.command[0]->u.word, c->u.command[0]);
      }
      else
      {
        execute_command (c->u.command[0], 0);
      }
      
      if(c->u.command[1]->type == SIMPLE_COMMAND)
      {
        c->u.command[1]->status = exec_simple_command(c->u.command[1]->u.word, c->u.command[1]);
      }
      else
      {
        execute_command (c->u.command[1], 0);
      }

      c->status =  c->u.command[1]->status;
    }
      break;
      
    // PIPE: regardless of whether or not the first argument succeeds or fails, the second argument
      //will execute.  Therefore, the status of the pipe command is the same as the status of the second argument
    case PIPE_COMMAND:
    {
      int pid;
      int secondpid;
      int returnpid;
      int status;
      int saved_stdout = dup(1);
      int saved_stdin = dup(0);
      int pipefd[2];
      pipe(pipefd);
      
      pid = fork();
      
      if(pid == 0)    // 0 if child process
      {
        close(pipefd[1]);
        dup2(pipefd[0], 0);
        if(c->u.command[1]->type == SIMPLE_COMMAND)
        {
          exec_simple_command(c->u.command[1]->u.word, c->u.command[1]);
        }
        else
        {
          execute_command (c->u.command[1], 0);
        }
        exit(c->u.command[1]->status);
      }
      else
      {
        secondpid = fork();
        if (secondpid == 0) //0 if child process
        {
          close(pipefd[0]);
          dup2(pipefd[1], 1);
          if(c->u.command[0]->type == SIMPLE_COMMAND)
          {
            exec_simple_command(c->u.command[0]->u.word, c->u.command[0]);
          }
          else
          {
            execute_command (c->u.command[0], 0);
          }
          exit(c->u.command[0]->status);     
        }
        
        else
        {
          close(pipefd[0]);
          close(pipefd[1]);
          dup2(saved_stdin, 0);
          dup2(saved_stdout, 1);
          returnpid = waitpid(-1, &status, 0);
          if(returnpid == secondpid)
          {
            waitpid(pid, &status, 0);
            c->u.command[0]->status = WEXITSTATUS(status);
          }
          if(returnpid == pid)
          {
            waitpid(secondpid, &status, 0);
            if(c->u.command[1]->type == SIMPLE_COMMAND)
            {
              c->u.command[1]->status = WEXITSTATUS(status);
            }
            else
            {
              execute_command (c->u.command[1], 0);
            }
            c->status = c->u.command[1]->status;
          }
        }
      }
    }
      break;
      
      
    case SIMPLE_COMMAND:
      c->status = exec_simple_command(c->u.word, c);
      break;
      
      
    case SUBSHELL_COMMAND:
    {
      int pid;      // 0 if child process
      int status;
      int in;
      int out;
      int saved_stdout = dup(1);
      int saved_stdin = dup(0);

      pid = fork();
      
      // child process
      if(pid == 0)
      {
        // REDIRECTIONS
        // restoring stdout with dup2 in case there are redirections
        
        if(c->input != 0)
        {
          in = open(c->input, O_CREAT | O_RDONLY, 0644);
          dup2(in, 0);
          close(in);
        }
        
        if(c->output != 0)
        {
          out = open(c->output, O_CREAT | O_TRUNC | O_WRONLY, 0622);
          dup2(out, 1);
          close(out);
        }
        
        execute_command(c->u.subshell_command, 0);
        exit(c->u.subshell_command->status);
      }
      
      // parent process
      else
      {
        dup2(saved_stdout, 1);
        dup2(saved_stdin, 0);
        // wait for child to terminate
        // store in variable status lots of info about the child process
        // pid_t waitpid(pid_t pid, int *status, int options);
        // The waitpid() system call suspends execution of the calling process 
        // until a child specified by pid argument has changed state.
        waitpid(pid, &status, 0);
        
        //take the last 8 bits of variable status --> data that we want for the exit status
        c->status = WEXITSTATUS(status);
      }    
    }
      break;
      
    default:
    {
      fprintf(stderr, "Invalid command type.");
      exit(1);
    }
  }
}
Esempio n. 3
0
static void
fork_exec_cb (const char *command,
              Screen *screen, Window window, Drawable drawable,
              void (*callback) (Screen *, Window, Drawable,
                                const char *name, XRectangle *geom,
                                void *closure),
              void *closure)
{
  XtAppContext app = XtDisplayToApplicationContext (DisplayOfScreen (screen));
  grabclient_data *data;
  char buf [255];
  pid_t forked;

  int fds [2];

  if (pipe (fds))
    {
      sprintf (buf, "%s: creating pipe", progname);
      perror (buf);
      exit (1);
    }

  data = (grabclient_data *) calloc (1, sizeof(*data));
  data->callback   = callback;
  data->closure    = closure;
  data->screen     = screen;
  data->window     = window;
  data->drawable   = drawable;
  data->read_pipe  = fdopen (fds[0], "r");
  data->write_pipe = fdopen (fds[1], "w");

  if (!data->read_pipe || !data->write_pipe)
    {
      sprintf (buf, "%s: fdopen", progname);
      perror (buf);
      exit (1);
    }

  data->pipe_id =
    XtAppAddInput (app, fileno (data->read_pipe),
                   (XtPointer) (XtInputReadMask | XtInputExceptMask),
                   finalize_cb, (XtPointer) data);

  forked = fork ();
  switch ((int) forked)
    {
    case -1:
      sprintf (buf, "%s: couldn't fork", progname);
      perror (buf);
      return;

    case 0:					/* child */

      fclose (data->read_pipe);
      data->read_pipe = 0;

      /* clone the write pipe onto stdout so that it gets closed
         when the fork exits.  This will shut down the pipe and
         signal the parent.
       */
      close (fileno (stdout));
      dup2 (fds[1], fileno (stdout));
      close (fds[1]);

      close (fileno (stdin)); /* for kicks */

      exec_simple_command (command);
      exit (1);  /* exits child fork */
      break;

    default:					/* parent */
      fclose (data->write_pipe);
      data->write_pipe = 0;
      data->pid = forked;
      break;
    }
}