If FD_CLOEXEC works, create a pipe and use it to report any errors that occur
while trying to execute the program.
This commit is contained in:
parent
0b9fe28288
commit
81dfe2ae09
85
master.c
85
master.c
|
|
@ -106,7 +106,7 @@ setnonblocking(int fd)
|
||||||
|
|
||||||
/* Initialize the pty structure. */
|
/* Initialize the pty structure. */
|
||||||
static int
|
static int
|
||||||
init_pty(char **argv)
|
init_pty(char **argv, int statusfd)
|
||||||
{
|
{
|
||||||
/* Use the original terminal's settings. We don't have to set the
|
/* Use the original terminal's settings. We don't have to set the
|
||||||
** window size here, because the attacher will send it in a packet. */
|
** window size here, because the attacher will send it in a packet. */
|
||||||
|
|
@ -124,9 +124,18 @@ init_pty(char **argv)
|
||||||
{
|
{
|
||||||
/* Child.. Execute the program. */
|
/* Child.. Execute the program. */
|
||||||
execvp(*argv, argv);
|
execvp(*argv, argv);
|
||||||
printf(EOS "\r\n%s: could not execute %s: %s\r\n",
|
|
||||||
progname, *argv, strerror(errno));
|
/* Report the error to statusfd if we can, or stdout if we
|
||||||
exit(127);
|
** can't. */
|
||||||
|
if (statusfd != -1)
|
||||||
|
dup2(statusfd, 1);
|
||||||
|
else
|
||||||
|
printf(EOS "\r\n");
|
||||||
|
|
||||||
|
printf("%s: could not execute %s: %s\r\n", progname,
|
||||||
|
*argv, strerror(errno));
|
||||||
|
fflush(stdout);
|
||||||
|
_exit(127);
|
||||||
}
|
}
|
||||||
/* Parent.. Finish up and return */
|
/* Parent.. Finish up and return */
|
||||||
#ifdef BROKEN_MASTER
|
#ifdef BROKEN_MASTER
|
||||||
|
|
@ -396,7 +405,7 @@ client_activity(struct client *p)
|
||||||
/* The master process - It watches over the pty process and the attached */
|
/* The master process - It watches over the pty process and the attached */
|
||||||
/* clients. */
|
/* clients. */
|
||||||
static void
|
static void
|
||||||
master_process(int s, char **argv, int waitattach)
|
master_process(int s, char **argv, int waitattach, int statusfd)
|
||||||
{
|
{
|
||||||
struct client *p, *next;
|
struct client *p, *next;
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
|
|
@ -407,12 +416,8 @@ master_process(int s, char **argv, int waitattach)
|
||||||
** don't care what happens to it. */
|
** don't care what happens to it. */
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
/* Create a pty in which the process is running. */
|
/* Set a trap to unlink the socket when we die. */
|
||||||
if (init_pty(argv) < 0)
|
atexit(unlink_socket);
|
||||||
{
|
|
||||||
printf("%s: init_pty: %s\n", progname, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up some signals. */
|
/* Set up some signals. */
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
@ -424,6 +429,19 @@ master_process(int s, char **argv, int waitattach)
|
||||||
signal(SIGTERM, die);
|
signal(SIGTERM, die);
|
||||||
signal(SIGCHLD, die);
|
signal(SIGCHLD, die);
|
||||||
|
|
||||||
|
/* Create a pty in which the process is running. */
|
||||||
|
if (init_pty(argv, statusfd) < 0)
|
||||||
|
{
|
||||||
|
if (statusfd != -1)
|
||||||
|
dup2(statusfd, 1);
|
||||||
|
printf("%s: init_pty: %s\n", progname, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close statusfd, since we don't need it anymore. */
|
||||||
|
if (statusfd != -1)
|
||||||
|
close(statusfd);
|
||||||
|
|
||||||
/* Make sure stdin/stdout/stderr point to /dev/null. We are now a
|
/* Make sure stdin/stdout/stderr point to /dev/null. We are now a
|
||||||
** daemon. */
|
** daemon. */
|
||||||
nullfd = open("/dev/null", O_RDWR);
|
nullfd = open("/dev/null", O_RDWR);
|
||||||
|
|
@ -433,9 +451,6 @@ master_process(int s, char **argv, int waitattach)
|
||||||
if (nullfd > 2)
|
if (nullfd > 2)
|
||||||
close(nullfd);
|
close(nullfd);
|
||||||
|
|
||||||
/* Set a trap to unlink the socket when we die. */
|
|
||||||
atexit(unlink_socket);
|
|
||||||
|
|
||||||
/* Loop forever. */
|
/* Loop forever. */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|
@ -494,6 +509,7 @@ master_process(int s, char **argv, int waitattach)
|
||||||
int
|
int
|
||||||
master_main(char **argv, int waitattach)
|
master_main(char **argv, int waitattach)
|
||||||
{
|
{
|
||||||
|
int fd[2] = {-1, -1};
|
||||||
int s;
|
int s;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
|
@ -509,20 +525,59 @@ master_main(char **argv, int waitattach)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||||
|
fcntl(s, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
/* If FD_CLOEXEC works, create a pipe and use it to report any errors
|
||||||
|
** that occur while trying to execute the program. */
|
||||||
|
if (pipe(fd) >= 0)
|
||||||
|
{
|
||||||
|
if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0 ||
|
||||||
|
fcntl(fd[1], F_SETFD, FD_CLOEXEC) < 0)
|
||||||
|
{
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
fd[0] = fd[1] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Fork off so we can daemonize and such */
|
/* Fork off so we can daemonize and such */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
printf("%s: fork: %s\n", progname, strerror(errno));
|
printf("%s: fork: %s\n", progname, strerror(errno));
|
||||||
|
unlink_socket();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (pid == 0)
|
else if (pid == 0)
|
||||||
{
|
{
|
||||||
/* Child - this becomes the master */
|
/* Child - this becomes the master */
|
||||||
master_process(s, argv, waitattach);
|
if (fd[0] != -1)
|
||||||
|
close(fd[0]);
|
||||||
|
master_process(s, argv, waitattach, fd[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Parent - just return. */
|
/* Parent - just return. */
|
||||||
|
|
||||||
|
#if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||||
|
/* Check if an error occurred while trying to execute the program. */
|
||||||
|
if (fd[0] != -1)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
close(fd[1]);
|
||||||
|
len = read(fd[0], buf, sizeof(buf));
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
write(2, buf, len);
|
||||||
|
kill(pid, SIGTERM);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
close(fd[0]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
close(s);
|
close(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue