* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 support by Markus Friedl.
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
#include "includes.h"
-RCSID("$OpenBSD: serverloop.c,v 1.65 2001/05/08 19:17:31 markus Exp $");
+RCSID("$OpenBSD: serverloop.c,v 1.71 2001/06/25 08:25:39 markus Exp $");
#include "xmalloc.h"
#include "packet.h"
* will exit after that, as soon as forwarded connections have terminated.
*/
-static pid_t child_pid; /* Pid of the child. */
static volatile int child_terminated; /* The child has terminated. */
-static volatile int child_wait_status; /* Status from wait(). */
-void server_init_dispatch(void);
+/* prototypes */
+static void server_init_dispatch(void);
int client_alive_timeouts = 0;
-void
+static void
sigchld_handler(int sig)
-{
- int save_errno = errno;
- pid_t wait_pid;
-
- debug("Received SIGCHLD.");
- wait_pid = wait((int *) &child_wait_status);
- if (wait_pid != -1) {
- if (wait_pid != child_pid)
- error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
- wait_pid, child_pid);
- if (WIFEXITED(child_wait_status) ||
- WIFSIGNALED(child_wait_status))
- child_terminated = 1;
- }
- signal(SIGCHLD, sigchld_handler);
- errno = save_errno;
-}
-void
-sigchld_handler2(int sig)
{
int save_errno = errno;
debug("Received SIGCHLD.");
child_terminated = 1;
- mysignal(SIGCHLD, sigchld_handler2);
+ mysignal(SIGCHLD, sigchld_handler);
errno = save_errno;
}
* Make packets from buffered stderr data, and buffer it for sending
* to the client.
*/
-void
+static void
make_packets_from_stderr_data(void)
{
int len;
* Make packets from buffered stdout data, and buffer it for sending to the
* client.
*/
-void
+static void
make_packets_from_stdout_data(void)
{
int len;
* have data or can accept data. Optionally, a maximum time can be specified
* for the duration of the wait (0 = infinite).
*/
-void
+static void
wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
u_int max_time_milliseconds)
{
* Processes input from the client and the program. Input data is stored
* in buffers and processed later.
*/
-void
+static void
process_input(fd_set * readset)
{
int len;
/*
* Sends data from internal buffers to client program stdin.
*/
-void
+static void
process_output(fd_set * writeset)
{
struct termios tio;
* Wait until all buffered output has been sent to the client.
* This is used when the program terminates.
*/
-void
+static void
drain_output(void)
{
/* Send any buffered stdout data to the client. */
packet_write_wait();
}
-void
+static void
process_buffered_input_packets(void)
{
dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
debug("Entering interactive session.");
/* Initialize the SIGCHLD kludge. */
- child_pid = pid;
child_terminated = 0;
signal(SIGCHLD, sigchld_handler);
close(fdin);
fdin = -1;
- /* Stop listening for channels; this removes unix domain sockets. */
- channel_stop_listening();
-
- /* Wait for the child to exit. Get its exit status. */
- wait_pid = wait(&wait_status);
- if (wait_pid == -1) {
- /*
- * It is possible that the wait was handled by SIGCHLD
- * handler. This may result in either: this call
- * returning with EINTR, or: this call returning ECHILD.
- */
- if (child_terminated)
- wait_status = child_wait_status;
- else
- packet_disconnect("wait: %.100s", strerror(errno));
- } else {
- /* Check if it matches the process we forked. */
- if (wait_pid != pid)
- error("Strange, wait returned pid %d, expected %d",
- wait_pid, pid);
- }
+ channel_free_all();
/* We no longer want our SIGCHLD handler to be called. */
signal(SIGCHLD, SIG_DFL);
+ wait_pid = waitpid(-1, &wait_status, child_terminated ? WNOHANG : 0);
+ if (wait_pid == -1)
+ packet_disconnect("wait: %.100s", strerror(errno));
+ else if (wait_pid != pid)
+ error("Strange, wait returned pid %d, expected %d",
+ wait_pid, pid);
+
/* Check if it exited normally. */
if (WIFEXITED(wait_status)) {
/* Yes, normal exit. Get exit status and send it to the client. */
debug("Entering interactive session for SSH2.");
- mysignal(SIGCHLD, sigchld_handler2);
+ mysignal(SIGCHLD, sigchld_handler);
child_terminated = 0;
connection_in = packet_get_connection_in();
connection_out = packet_get_connection_out();
if (writeset)
xfree(writeset);
+ channel_free_all();
+
signal(SIGCHLD, SIG_DFL);
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
session_close_by_pid(pid, status);
- channel_stop_listening();
}
-void
+static void
server_input_channel_failure(int type, int plen, void *ctxt)
{
debug("Got CHANNEL_FAILURE for keepalive");
}
-void
+static void
server_input_stdin_data(int type, int plen, void *ctxt)
{
char *data;
xfree(data);
}
-void
+static void
server_input_eof(int type, int plen, void *ctxt)
{
/*
stdin_eof = 1;
}
-void
+static void
server_input_window_size(int type, int plen, void *ctxt)
{
int row = packet_get_int();
pty_change_window_size(fdin, row, col, xpixel, ypixel);
}
-Channel *
+static Channel *
server_request_direct_tcpip(char *ctype)
{
Channel *c;
return c;
}
-Channel *
+static Channel *
server_request_session(char *ctype)
{
Channel *c;
return c;
}
-void
+static void
server_input_channel_open(int type, int plen, void *ctxt)
{
Channel *c = NULL;
xfree(ctype);
}
-void
+static void
server_input_global_request(int type, int plen, void *ctxt)
{
char *rtype;
xfree(rtype);
}
-void
+static void
server_init_dispatch_20(void)
{
debug("server_init_dispatch_20");
/* rekeying */
dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
}
-void
+static void
server_init_dispatch_13(void)
{
debug("server_init_dispatch_13");
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
}
-void
+static void
server_init_dispatch_15(void)
{
server_init_dispatch_13();
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
}
-void
+static void
server_init_dispatch(void)
{
if (compat20)