pid_t exec_pty()

in native/exec_pty.c [118:206]


pid_t exec_pty(const char *path, char *const argv[], char *const envp[], const char *dirpath,
		       const char *pts_name, int fdm, const char *err_pts_name, int err_fdm, int console)
{
	pid_t childpid;
	char *full_path;

	/*
	 * We use pfind() to check that the program exists and is an executable.
	 * If not pass the error up.  Also execve() wants a full path.
	 */ 
	full_path = pfind(path, envp);
	if (full_path == NULL) {
		fprintf(stderr, "Unable to find full path for \"%s\"\n", (path) ? path : "");
		return -1;
	}

	childpid = fork();

	if (childpid < 0) {
		fprintf(stderr, "%s(%d): returning due to error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
		free(full_path);
		return -1;
	} else if (childpid == 0) { /* child */

		chdir(dirpath);

		int fds;
		int err_fds = -1;

		if (!console && setsid() < 0) {
			perror("setsid()");
			return -1;
		}

		fds = ptys_open(fdm, pts_name, true);
		if (fds < 0) {
			fprintf(stderr, "%s(%d): returning due to error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
			return -1;
		}

		if (console && err_fdm >= 0) {
			err_fds = ptys_open(err_fdm, err_pts_name, false);
			if (err_fds < 0) {
				fprintf(stderr, "%s(%d): returning due to error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
				return -1;
			}
		}

		/* close masters, no need in the child */
		close(fdm);
		if (console && err_fdm >= 0) close(err_fdm);

		if (console) {
			set_noecho(fds);
			if (setpgid(getpid(), getpid()) < 0) {
				perror("setpgid()");
				return -1;
			}
		}

		/* redirections */
		dup2(fds, STDIN_FILENO);   /* dup stdin */
		dup2(fds, STDOUT_FILENO);  /* dup stdout */
		dup2(console && err_fds >= 0 ? err_fds : fds, STDERR_FILENO);  /* dup stderr */

		close(fds);  /* done with fds. */
		if (console && err_fds >= 0) close(err_fds);

		/* Close all the fd's in the child */
        close_all_fds();

		restore_signals();

		execve(full_path, argv, envp);

		_exit(127);

	} else if (childpid != 0) { /* parent */
		if (console) {
			set_noecho(fdm);
		}

		free(full_path);
		return childpid;
	}

	free(full_path);
	return -1;                  /*NOT REACHED */
}