version 1.252, 2010/03/07 11:57:13 |
version 1.253, 2010/04/23 22:42:05 |
|
|
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
#include <errno.h> |
#include <errno.h> |
|
#include <fcntl.h> |
#include <grp.h> |
#include <grp.h> |
#include <login_cap.h> |
#include <login_cap.h> |
#include <paths.h> |
#include <paths.h> |
|
|
#ifdef USE_PIPES |
#ifdef USE_PIPES |
int pin[2], pout[2], perr[2]; |
int pin[2], pout[2], perr[2]; |
|
|
|
if (s == NULL) |
|
fatal("do_exec_no_pty: no session"); |
|
|
/* Allocate pipes for communicating with the program. */ |
/* Allocate pipes for communicating with the program. */ |
if (pipe(pin) < 0) { |
if (pipe(pin) < 0) { |
error("%s: pipe in: %.100s", __func__, strerror(errno)); |
error("%s: pipe in: %.100s", __func__, strerror(errno)); |
|
|
close(pin[1]); |
close(pin[1]); |
return -1; |
return -1; |
} |
} |
if (pipe(perr) < 0) { |
if (s->is_subsystem) { |
error("%s: pipe err: %.100s", __func__, strerror(errno)); |
if ((perr[1] = open(_PATH_DEVNULL, O_WRONLY)) == -1) { |
close(pin[0]); |
error("%s: open(%s): %s", __func__, _PATH_DEVNULL, |
close(pin[1]); |
strerror(errno)); |
close(pout[0]); |
close(pin[0]); |
close(pout[1]); |
close(pin[1]); |
return -1; |
close(pout[0]); |
|
close(pout[1]); |
|
return -1; |
|
} |
|
perr[0] = -1; |
|
} else { |
|
if (pipe(perr) < 0) { |
|
error("%s: pipe err: %.100s", __func__, |
|
strerror(errno)); |
|
close(pin[0]); |
|
close(pin[1]); |
|
close(pout[0]); |
|
close(pout[1]); |
|
return -1; |
|
} |
} |
} |
#else |
#else |
int inout[2], err[2]; |
int inout[2], err[2]; |
|
|
|
if (s == NULL) |
|
fatal("do_exec_no_pty: no session"); |
|
|
/* Uses socket pairs to communicate with the program. */ |
/* Uses socket pairs to communicate with the program. */ |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { |
error("%s: socketpair #1: %.100s", __func__, strerror(errno)); |
error("%s: socketpair #1: %.100s", __func__, strerror(errno)); |
return -1; |
return -1; |
} |
} |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { |
if (s->is_subsystem) { |
error("%s: socketpair #2: %.100s", __func__, strerror(errno)); |
if ((err[0] = open(_PATH_DEVNULL, O_WRONLY)) == -1) { |
close(inout[0]); |
error("%s: open(%s): %s", __func__, _PATH_DEVNULL, |
close(inout[1]); |
strerror(errno)); |
return -1; |
close(inout[0]); |
|
close(inout[1]); |
|
return -1; |
|
} |
|
err[1] = -1; |
|
} else { |
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { |
|
error("%s: socketpair #2: %.100s", __func__, |
|
strerror(errno)); |
|
close(inout[0]); |
|
close(inout[1]); |
|
return -1; |
|
} |
} |
} |
#endif |
#endif |
|
|
if (s == NULL) |
|
fatal("do_exec_no_pty: no session"); |
|
|
|
session_proctitle(s); |
session_proctitle(s); |
|
|
/* Fork the child. */ |
/* Fork the child. */ |
|
|
close(pin[1]); |
close(pin[1]); |
close(pout[0]); |
close(pout[0]); |
close(pout[1]); |
close(pout[1]); |
close(perr[0]); |
if (perr[0] != -1) |
|
close(perr[0]); |
close(perr[1]); |
close(perr[1]); |
#else |
#else |
close(inout[0]); |
close(inout[0]); |
close(inout[1]); |
close(inout[1]); |
close(err[0]); |
close(err[0]); |
close(err[1]); |
if (err[1] != -1) |
|
close(err[1]); |
#endif |
#endif |
return -1; |
return -1; |
case 0: |
case 0: |
|
|
close(pout[1]); |
close(pout[1]); |
|
|
/* Redirect stderr. */ |
/* Redirect stderr. */ |
close(perr[0]); |
if (perr[0] != -1) |
|
close(perr[0]); |
if (dup2(perr[1], 2) < 0) |
if (dup2(perr[1], 2) < 0) |
perror("dup2 stderr"); |
perror("dup2 stderr"); |
close(perr[1]); |
close(perr[1]); |
|
|
* seem to depend on it. |
* seem to depend on it. |
*/ |
*/ |
close(inout[1]); |
close(inout[1]); |
close(err[1]); |
if (err[1] != -1) |
|
close(err[1]); |
if (dup2(inout[0], 0) < 0) /* stdin */ |
if (dup2(inout[0], 0) < 0) /* stdin */ |
perror("dup2 stdin"); |
perror("dup2 stdin"); |
if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ |
if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ |
|
|
close(perr[1]); |
close(perr[1]); |
|
|
if (compat20) { |
if (compat20) { |
if (s->is_subsystem) { |
|
close(perr[0]); |
|
perr[0] = -1; |
|
} |
|
session_set_fds(s, pin[1], pout[0], perr[0], 0); |
session_set_fds(s, pin[1], pout[0], perr[0], 0); |
} else { |
} else { |
/* Enter the interactive session. */ |
/* Enter the interactive session. */ |
|
|
* handle the case that fdin and fdout are the same. |
* handle the case that fdin and fdout are the same. |
*/ |
*/ |
if (compat20) { |
if (compat20) { |
session_set_fds(s, inout[1], inout[1], |
session_set_fds(s, inout[1], inout[1], err[1], 0); |
s->is_subsystem ? -1 : err[1], 0); |
|
if (s->is_subsystem) |
|
close(err[1]); |
|
} else { |
} else { |
server_loop(pid, inout[1], inout[1], err[1]); |
server_loop(pid, inout[1], inout[1], err[1]); |
/* server_loop has closed inout[1] and err[1]. */ |
/* server_loop has closed inout[1] and err[1]. */ |