version 1.74.2.2, 2001/09/27 19:03:55 |
version 1.74.2.3, 2001/11/15 00:15:19 |
|
|
/* Make the pseudo tty our controlling tty. */ |
/* Make the pseudo tty our controlling tty. */ |
pty_make_controlling_tty(&ttyfd, s->tty); |
pty_make_controlling_tty(&ttyfd, s->tty); |
|
|
/* Redirect stdin from the pseudo tty. */ |
/* Redirect stdin/stdout/stderr from the pseudo tty. */ |
if (dup2(ttyfd, fileno(stdin)) < 0) |
if (dup2(ttyfd, 0) < 0) |
error("dup2 stdin failed: %.100s", strerror(errno)); |
error("dup2 stdin: %s", strerror(errno)); |
|
if (dup2(ttyfd, 1) < 0) |
|
error("dup2 stdout: %s", strerror(errno)); |
|
if (dup2(ttyfd, 2) < 0) |
|
error("dup2 stderr: %s", strerror(errno)); |
|
|
/* Redirect stdout to the pseudo tty. */ |
|
if (dup2(ttyfd, fileno(stdout)) < 0) |
|
error("dup2 stdin failed: %.100s", strerror(errno)); |
|
|
|
/* Redirect stderr to the pseudo tty. */ |
|
if (dup2(ttyfd, fileno(stderr)) < 0) |
|
error("dup2 stdin failed: %.100s", strerror(errno)); |
|
|
|
/* Close the extra descriptor for the pseudo tty. */ |
/* Close the extra descriptor for the pseudo tty. */ |
close(ttyfd); |
close(ttyfd); |
|
|
|
|
for (i = 3; i < 64; i++) |
for (i = 3; i < 64; i++) |
close(i); |
close(i); |
|
|
/* Change current directory to the user\'s home directory. */ |
|
if (chdir(pw->pw_dir) < 0) { |
|
fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
|
pw->pw_dir, strerror(errno)); |
|
#ifdef HAVE_LOGIN_CAP |
|
if (login_getcapbool(lc, "requirehome", 0)) |
|
exit(1); |
|
#endif |
|
} |
|
|
|
/* |
/* |
* Must take new environment into use so that .ssh/rc, /etc/sshrc and |
* Must take new environment into use so that .ssh/rc, /etc/sshrc and |
* xauth are run in the proper environment. |
* xauth are run in the proper environment. |
|
|
} |
} |
#endif /* AFS */ |
#endif /* AFS */ |
|
|
|
/* Change current directory to the user\'s home directory. */ |
|
if (chdir(pw->pw_dir) < 0) { |
|
fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
|
pw->pw_dir, strerror(errno)); |
|
#ifdef HAVE_LOGIN_CAP |
|
if (login_getcapbool(lc, "requirehome", 0)) |
|
exit(1); |
|
#endif |
|
} |
|
|
/* |
/* |
* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first |
* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first |
* in this order). |
* in this order). |
|
|
static int |
static int |
session_subsystem_req(Session *s) |
session_subsystem_req(Session *s) |
{ |
{ |
|
struct stat st; |
u_int len; |
u_int len; |
int success = 0; |
int success = 0; |
char *subsys = packet_get_string(&len); |
char *cmd, *subsys = packet_get_string(&len); |
int i; |
int i; |
|
|
packet_done(); |
packet_done(); |
log("subsystem request for %s", subsys); |
log("subsystem request for %s", subsys); |
|
|
for (i = 0; i < options.num_subsystems; i++) { |
for (i = 0; i < options.num_subsystems; i++) { |
if(strcmp(subsys, options.subsystem_name[i]) == 0) { |
if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
debug("subsystem: exec() %s", options.subsystem_command[i]); |
cmd = options.subsystem_command[i]; |
|
if (stat(cmd, &st) < 0) { |
|
error("subsystem: cannot stat %s: %s", cmd, |
|
strerror(errno)); |
|
break; |
|
} |
|
debug("subsystem: exec() %s", cmd); |
s->is_subsystem = 1; |
s->is_subsystem = 1; |
do_exec(s, options.subsystem_command[i]); |
do_exec(s, cmd); |
success = 1; |
success = 1; |
} |
} |
} |
} |
|
|
if (!success) |
if (!success) |
log("subsystem request for %s failed, subsystem not found", subsys); |
log("subsystem request for %s failed, subsystem not found", |
|
subsys); |
|
|
xfree(subsys); |
xfree(subsys); |
return success; |
return success; |
|
|
*/ |
*/ |
if (close(s->ptymaster) < 0) |
if (close(s->ptymaster) < 0) |
error("close(s->ptymaster): %s", strerror(errno)); |
error("close(s->ptymaster): %s", strerror(errno)); |
|
|
|
/* unlink pty from session */ |
|
s->ttyfd = -1; |
} |
} |
|
|
static void |
static void |
|
|
session_close(s); |
session_close(s); |
} |
} |
|
|
int |
|
session_have_children(void) |
|
{ |
|
int i; |
|
|
|
for(i = 0; i < MAX_SESSIONS; i++) { |
|
Session *s = &sessions[i]; |
|
if (s->used && s->pid != -1) { |
|
debug("session_have_children: id %d pid %d", i, s->pid); |
|
return 1; |
|
} |
|
} |
|
debug("session_have_children: no more children"); |
|
return 0; |
|
} |
|
|
|
/* |
/* |
* this is called when a channel dies before |
* this is called when a channel dies before |
* the session 'child' itself dies |
* the session 'child' itself dies |
|
|
{ |
{ |
Session *s = session_by_channel(id); |
Session *s = session_by_channel(id); |
if (s == NULL) { |
if (s == NULL) { |
debug("session_close_by_channel: no session for channel %d", id); |
debug("session_close_by_channel: no session for id %d", id); |
return; |
return; |
} |
} |
/* disconnect channel */ |
debug("session_close_by_channel: channel %d child %d", id, s->pid); |
|
if (s->pid != 0) { |
|
debug("session_close_by_channel: channel %d: has child", id); |
|
/* |
|
* delay detach of session, but release pty, since |
|
* the fd's to the child are already closed |
|
*/ |
|
if (s->ttyfd != -1) { |
|
fatal_remove_cleanup(session_pty_cleanup, (void *)s); |
|
session_pty_cleanup(s); |
|
} |
|
return; |
|
} |
|
/* detach by removing callback */ |
channel_cancel_cleanup(s->chanid); |
channel_cancel_cleanup(s->chanid); |
s->chanid = -1; |
s->chanid = -1; |
|
session_close(s); |
|
} |
|
|
debug("session_close_by_channel: channel %d kill %d", id, s->pid); |
void |
if (s->pid == 0) { |
session_destroy_all(void) |
/* close session immediately */ |
{ |
session_close(s); |
int i; |
} else { |
for(i = 0; i < MAX_SESSIONS; i++) { |
/* notify child, delay session cleanup */ |
Session *s = &sessions[i]; |
if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0) |
if (s->used) |
error("session_close_by_channel: kill %d: %s", |
session_close(s); |
s->pid, strerror(errno)); |
|
} |
} |
} |
} |
|
|