Esempio n. 1
0
/* Create pty and fork/exec target process */
pid_t exec_target(int master_fd, char* argv[], int pty_alloc_only)
{
  pid_t pid;

  pid = fork();

  if (pid < 0) {
    perror("Failed to fork");
    exit(EXIT_FAILURE);
  }

  if (pid == 0) {
    int slave_fd;
    int i;

    /* new session for obtain ctty */
    if (setsid() < 0) {
      perror("Failed to setsid");
      exit(EXIT_FAILURE);
    }

    slave_fd = open(ptsname(master_fd), O_RDWR);
    close(master_fd);

    if (slave_fd < 0) {
      perror("Failed to open slave pty");
      exit(EXIT_FAILURE);
    }

    if (pty_alloc_only)
      set_tty_echo_on(slave_fd);

    for (i = 0; i < 3; i++) {
      if (slave_fd != i) {
	dup2(slave_fd, i);
	fcntl(i, F_SETFD, 0);
      }
    }
    if (slave_fd > 2)
      close(slave_fd);

    /* make new process group and make it foreground */
    if (setpgid(0, 0) < 0)
      perror("Failed to setpgid");
    if (tcsetpgrp(0, getpgid(getpid())) < 0)
      perror("Failed to change foreground pgid");

    if (pty_alloc_only)
      /* do nothing. wait for kill */
      select(0, NULL, NULL, NULL, NULL);
    else
      execvp(argv[0], argv);

    fprintf(stderr, "Failed to execute \"%s\": %s\n", argv[0], strerror(errno));
    exit(EXIT_FAILURE);
  }

  return pid;
}
Esempio n. 2
0
int main(int argc, char* argv[])
{
  fd_set sel, sel0;
  int status;
  int pty_hold_mode = FALSE;
  char* newarg0;

  /* SIGINT and SIGBREAK are indistinctive under cygwin environment. */
  /* Using Win32API to handle SIGINT.                               */
  SetConsoleCtrlHandler(ctrl_handler, TRUE);

  if (argc < 1) {
    fputs("Unable to get arg[0].", stderr);
    exit(EXIT_FAILURE);
  }

  newarg0 = real_command_name(argv[0]);

  if (newarg0)
    argv[0] = newarg0;
  else if (argc >=2)
    argv++;
  else
    pty_hold_mode = TRUE;

  if (isatty(STDIN_FILENO) && !pty_hold_mode) {
    execvp(argv[0], argv);
    fprintf(stderr, "Failed to execute \"%s\": %s\n", argv[0], strerror(errno));
    exit(EXIT_FAILURE);
  }

  masterfd = open_master_pty();

  if (!pty_hold_mode)
    child_pid = exec_target(masterfd, argv);
  else
    set_tty_echo_on(masterfd);

  setup_signal_handlers();

  FD_ZERO(&sel0);
  FD_SET(masterfd, &sel0);
  FD_SET(STDIN_FILENO, &sel0);

  /* communication loop */
  while (1) {
    char buf[BUFSIZE];
    int ret;

    if (sig_winch_caught == TRUE) {
      sig_winch_caught = FALSE;
      if (child_pid != -1 && resize_tty_window(masterfd, sig_window_size) == 0)
	kill(child_pid, SIGWINCH);
    }

    sel = sel0;
    if (select (FD_SETSIZE, &sel, NULL, NULL, NULL) <= 0) {
      if(errno == EINTR)
	continue;
      else
	break;
    }

    if (FD_ISSET(masterfd, &sel)) {
      ret = safe_read(masterfd, buf, BUFSIZE);
      if (ret > 0) {
	if (safe_write_full(STDOUT_FILENO, buf, ret) < 0)
	  break;
      }
      else
	break;
    }
    else if (FD_ISSET(STDIN_FILENO, &sel)) {
      ret = safe_read(STDIN_FILENO, buf, BUFSIZE);
      if (ret > 0) {
	if (safe_write_full_checking_eof(masterfd, buf, ret) < 0)
	  break;
      } else {
	FD_CLR(STDIN_FILENO, &sel0);
	close(masterfd);
      }
    }
  }

  if (pty_hold_mode) {
    status = 0;
  } else {
    while(waitpid(child_pid, &status, 0) < 0 && errno == EINTR)
      ;

    if (WIFEXITED(status))
      status = WEXITSTATUS(status);
    else if(WIFSIGNALED(status)) /* ntemacs cannot distinct killed by signal */
      status = 0x80 +  WTERMSIG(status);
  }

  return status;
}