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 */
}