5 Author: Tatu Ylonen <ylo@cs.hut.fi>
7 Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
10 Created: Sun Sep 10 00:30:37 1995 ylo
12 Server main loop for handling the interactive session.
24 static Buffer stdin_buffer; /* Buffer for stdin data. */
25 static Buffer stdout_buffer; /* Buffer for stdout data. */
26 static Buffer stderr_buffer; /* Buffer for stderr data. */
27 static int fdin; /* Descriptor for stdin (for writing) */
28 static int fdout; /* Descriptor for stdout (for reading);
29 May be same number as fdin. */
30 static int fderr; /* Descriptor for stderr. May be -1. */
31 static long stdin_bytes = 0; /* Number of bytes written to stdin. */
32 static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */
33 static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */
34 static long fdout_bytes = 0; /* Number of stdout bytes read from program. */
35 static int stdin_eof = 0; /* EOF message received from client. */
36 static int fdout_eof = 0; /* EOF encountered reading from fdout. */
37 static int fderr_eof = 0; /* EOF encountered readung from fderr. */
38 static int connection_in; /* Connection to client (input). */
39 static int connection_out; /* Connection to client (output). */
40 static unsigned int buffer_high;/* "Soft" max buffer size. */
41 static int max_fd; /* Max file descriptor number for select(). */
43 /* This SIGCHLD kludge is used to detect when the child exits. The server
44 will exit after that, as soon as forwarded connections have terminated. */
46 static int child_pid; /* Pid of the child. */
47 static volatile int child_terminated; /* The child has terminated. */
48 static volatile int child_wait_status; /* Status from wait(). */
50 void sigchld_handler(int sig)
52 int save_errno = errno;
54 debug("Received SIGCHLD.");
55 wait_pid = wait((int *)&child_wait_status);
58 if (wait_pid != child_pid)
59 error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
61 if (WIFEXITED(child_wait_status) ||
62 WIFSIGNALED(child_wait_status))
65 signal(SIGCHLD, sigchld_handler);
69 /* Process any buffered packets that have been received from the client. */
71 void process_buffered_input_packets()
75 unsigned int data_len;
76 int row, col, xpixel, ypixel;
79 /* Process buffered packets from the client. */
80 while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE)
84 case SSH_CMSG_STDIN_DATA:
85 /* Stdin data from the client. Append it to the buffer. */
87 break; /* Ignore any data if the client has closed stdin. */
88 data = packet_get_string(&data_len);
89 packet_integrity_check(payload_len, (4 + data_len), type);
90 buffer_append(&stdin_buffer, data, data_len);
91 memset(data, 0, data_len);
96 /* Eof from the client. The stdin descriptor to the program
97 will be closed when all buffered data has drained. */
98 debug("EOF received for stdin.");
99 packet_integrity_check(payload_len, 0, type);
103 case SSH_CMSG_WINDOW_SIZE:
104 debug("Window change received.");
105 packet_integrity_check(payload_len, 4*4, type);
106 row = packet_get_int();
107 col = packet_get_int();
108 xpixel = packet_get_int();
109 ypixel = packet_get_int();
111 pty_change_window_size(fdin, row, col, xpixel, ypixel);
114 case SSH_MSG_PORT_OPEN:
115 debug("Received port open request.");
116 channel_input_port_open(payload_len);
119 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
120 debug("Received channel open confirmation.");
121 packet_integrity_check(payload_len, 4 + 4, type);
122 channel_input_open_confirmation();
125 case SSH_MSG_CHANNEL_OPEN_FAILURE:
126 debug("Received channel open failure.");
127 packet_integrity_check(payload_len, 4, type);
128 channel_input_open_failure();
131 case SSH_MSG_CHANNEL_DATA:
132 channel_input_data(payload_len);
135 case SSH_MSG_CHANNEL_CLOSE:
136 debug("Received channel close.");
137 packet_integrity_check(payload_len, 4, type);
138 channel_input_close();
141 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
142 debug("Received channel close confirmation.");
143 packet_integrity_check(payload_len, 4, type);
144 channel_input_close_confirmation();
148 /* In this phase, any unexpected messages cause a protocol
149 error. This is to ease debugging; also, since no
150 confirmations are sent messages, unprocessed unknown
151 messages could cause strange problems. Any compatible
152 protocol extensions must be negotiated before entering the
153 interactive session. */
154 packet_disconnect("Protocol error during session: type %d",
160 /* Make packets from buffered stderr data, and buffer it for sending
163 void make_packets_from_stderr_data()
167 /* Send buffered stderr data to the client. */
168 while (buffer_len(&stderr_buffer) > 0 &&
169 packet_not_very_much_data_to_write())
171 len = buffer_len(&stderr_buffer);
172 if (packet_is_interactive())
180 len = 32768; /* Keep the packets at reasonable size. */
182 packet_start(SSH_SMSG_STDERR_DATA);
183 packet_put_string(buffer_ptr(&stderr_buffer), len);
185 buffer_consume(&stderr_buffer, len);
190 /* Make packets from buffered stdout data, and buffer it for sending to the
193 void make_packets_from_stdout_data()
197 /* Send buffered stdout data to the client. */
198 while (buffer_len(&stdout_buffer) > 0 &&
199 packet_not_very_much_data_to_write())
201 len = buffer_len(&stdout_buffer);
202 if (packet_is_interactive())
210 len = 32768; /* Keep the packets at reasonable size. */
212 packet_start(SSH_SMSG_STDOUT_DATA);
213 packet_put_string(buffer_ptr(&stdout_buffer), len);
215 buffer_consume(&stdout_buffer, len);
220 /* Sleep in select() until we can do something. This will initialize the
221 select masks. Upon return, the masks will indicate which descriptors
222 have data or can accept data. Optionally, a maximum time can be specified
223 for the duration of the wait (0 = infinite). */
225 void wait_until_can_do_something(fd_set *readset, fd_set *writeset,
226 unsigned int max_time_milliseconds)
228 struct timeval tv, *tvp;
231 /* When select fails we restart from here. */
234 /* Initialize select() masks. */
237 /* Read packets from the client unless we have too much buffered stdin
239 if (buffer_len(&stdin_buffer) < 4096 &&
240 channel_not_very_much_buffered_data())
241 FD_SET(connection_in, readset);
243 /* If there is not too much data already buffered going to the client,
244 try to get some more data from the program. */
245 if (packet_not_very_much_data_to_write())
248 FD_SET(fdout, readset);
250 FD_SET(fderr, readset);
255 /* Set masks for channel descriptors. */
256 channel_prepare_select(readset, writeset);
258 /* If we have buffered packet data going to the client, mark that
260 if (packet_have_data_to_write())
261 FD_SET(connection_out, writeset);
263 /* If we have buffered data, try to write some of that data to the
265 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
266 FD_SET(fdin, writeset);
268 /* Update the maximum descriptor number if appropriate. */
269 if (channel_max_fd() > max_fd)
270 max_fd = channel_max_fd();
272 /* If child has terminated and there is enough buffer space to read from
273 it, then read as much as is available and exit. */
274 if (child_terminated && packet_not_very_much_data_to_write())
275 if (max_time_milliseconds == 0)
276 max_time_milliseconds = 100;
278 if (max_time_milliseconds == 0)
282 tv.tv_sec = max_time_milliseconds / 1000;
283 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
287 /* Wait for something to happen, or the timeout to expire. */
288 ret = select(max_fd + 1, readset, writeset, NULL, tvp);
293 error("select: %.100s", strerror(errno));
299 /* Processes input from the client and the program. Input data is stored
300 in buffers and processed later. */
302 void process_input(fd_set *readset)
307 /* Read and buffer any input data from the client. */
308 if (FD_ISSET(connection_in, readset))
310 len = read(connection_in, buf, sizeof(buf));
312 fatal("Connection closed by remote host.");
314 /* There is a kernel bug on Solaris that causes select to sometimes
315 wake up even though there is no data available. */
316 if (len < 0 && errno == EAGAIN)
320 fatal("Read error from remote host: %.100s", strerror(errno));
322 /* Buffer any received data. */
323 packet_process_incoming(buf, len);
326 /* Read and buffer any available stdout data from the program. */
327 if (!fdout_eof && FD_ISSET(fdout, readset))
329 len = read(fdout, buf, sizeof(buf));
334 buffer_append(&stdout_buffer, buf, len);
339 /* Read and buffer any available stderr data from the program. */
340 if (!fderr_eof && FD_ISSET(fderr, readset))
342 len = read(fderr, buf, sizeof(buf));
346 buffer_append(&stderr_buffer, buf, len);
350 /* Sends data from internal buffers to client program stdin. */
352 void process_output(fd_set *writeset)
356 /* Write buffered data to program stdin. */
357 if (fdin != -1 && FD_ISSET(fdin, writeset))
359 len = write(fdin, buffer_ptr(&stdin_buffer),
360 buffer_len(&stdin_buffer));
369 shutdown(fdin, SHUT_WR); /* We will no longer send. */
375 /* Successful write. Consume the data from the buffer. */
376 buffer_consume(&stdin_buffer, len);
377 /* Update the count of bytes written to the program. */
382 /* Send any buffered packet data to the client. */
383 if (FD_ISSET(connection_out, writeset))
387 /* Wait until all buffered output has been sent to the client.
388 This is used when the program terminates. */
392 /* Send any buffered stdout data to the client. */
393 if (buffer_len(&stdout_buffer) > 0)
395 packet_start(SSH_SMSG_STDOUT_DATA);
396 packet_put_string(buffer_ptr(&stdout_buffer),
397 buffer_len(&stdout_buffer));
399 /* Update the count of sent bytes. */
400 stdout_bytes += buffer_len(&stdout_buffer);
403 /* Send any buffered stderr data to the client. */
404 if (buffer_len(&stderr_buffer) > 0)
406 packet_start(SSH_SMSG_STDERR_DATA);
407 packet_put_string(buffer_ptr(&stderr_buffer),
408 buffer_len(&stderr_buffer));
410 /* Update the count of sent bytes. */
411 stderr_bytes += buffer_len(&stderr_buffer);
414 /* Wait until all buffered data has been written to the client. */
418 /* Performs the interactive session. This handles data transmission between
419 the client and the program. Note that the notion of stdin, stdout, and
420 stderr in this function is sort of reversed: this function writes to
421 stdin (of the child program), and reads from stdout and stderr (of the
424 void server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
426 int wait_status, wait_pid; /* Status and pid returned by wait(). */
427 int waiting_termination = 0; /* Have displayed waiting close message. */
428 unsigned int max_time_milliseconds;
429 unsigned int previous_stdout_buffer_bytes;
430 unsigned int stdout_buffer_bytes;
433 debug("Entering interactive session.");
435 /* Initialize the SIGCHLD kludge. */
437 child_terminated = 0;
438 signal(SIGCHLD, sigchld_handler);
440 /* Initialize our global variables. */
444 connection_in = packet_get_connection_in();
445 connection_out = packet_get_connection_out();
447 previous_stdout_buffer_bytes = 0;
449 /* Set approximate I/O buffer size. */
450 if (packet_is_interactive())
453 buffer_high = 64 * 1024;
455 /* Initialize max_fd to the maximum of the known file descriptors. */
459 if (fderr != -1 && fderr > max_fd)
461 if (connection_in > max_fd)
462 max_fd = connection_in;
463 if (connection_out > max_fd)
464 max_fd = connection_out;
466 /* Initialize Initialize buffers. */
467 buffer_init(&stdin_buffer);
468 buffer_init(&stdout_buffer);
469 buffer_init(&stderr_buffer);
471 /* If we have no separate fderr (which is the case when we have a pty - there
472 we cannot make difference between data sent to stdout and stderr),
473 indicate that we have seen an EOF from stderr. This way we don\'t
474 need to check the descriptor everywhere. */
478 /* Main loop of the server for the interactive session mode. */
481 fd_set readset, writeset;
483 /* Process buffered packets from the client. */
484 process_buffered_input_packets();
486 /* If we have received eof, and there is no more pending input data,
487 cause a real eof by closing fdin. */
488 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0)
496 shutdown(fdin, SHUT_WR); /* We will no longer send. */
501 /* Make packets from buffered stderr data to send to the client. */
502 make_packets_from_stderr_data();
504 /* Make packets from buffered stdout data to send to the client.
505 If there is very little to send, this arranges to not send them
506 now, but to wait a short while to see if we are getting more data.
507 This is necessary, as some systems wake up readers from a pty after
508 each separate character. */
509 max_time_milliseconds = 0;
510 stdout_buffer_bytes = buffer_len(&stdout_buffer);
511 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
512 stdout_buffer_bytes != previous_stdout_buffer_bytes)
513 max_time_milliseconds = 10; /* try again after a while */
515 make_packets_from_stdout_data(); /* Send it now. */
516 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
518 /* Send channel data to the client. */
519 if (packet_not_very_much_data_to_write())
520 channel_output_poll();
522 /* Bail out of the loop if the program has closed its output descriptors,
523 and we have no more data to send to the client, and there is no
524 pending buffered data. */
525 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
526 buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0)
528 if (!channel_still_open())
530 if (!waiting_termination)
533 "Waiting for forwarded connections to terminate...\r\n";
535 waiting_termination = 1;
536 buffer_append(&stderr_buffer, s, strlen(s));
538 /* Display list of open channels. */
539 cp = channel_open_message();
540 buffer_append(&stderr_buffer, cp, strlen(cp));
545 /* Sleep in select() until we can do something. */
546 wait_until_can_do_something(&readset, &writeset,
547 max_time_milliseconds);
549 /* Process any channel events. */
550 channel_after_select(&readset, &writeset);
552 /* Process input from the client and from program stdout/stderr. */
553 process_input(&readset);
555 /* Process output to the client and to program stdin. */
556 process_output(&writeset);
560 /* Cleanup and termination code. */
562 /* Wait until all output has been sent to the client. */
565 debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
566 stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
568 /* Free and clear the buffers. */
569 buffer_free(&stdin_buffer);
570 buffer_free(&stdout_buffer);
571 buffer_free(&stderr_buffer);
573 /* Close the file descriptors. */
586 /* Stop listening for channels; this removes unix domain sockets. */
587 channel_stop_listening();
589 /* Wait for the child to exit. Get its exit status. */
590 wait_pid = wait(&wait_status);
593 /* It is possible that the wait was handled by SIGCHLD handler. This
594 may result in either: this call returning with EINTR, or: this
595 call returning ECHILD. */
596 if (child_terminated)
597 wait_status = child_wait_status;
599 packet_disconnect("wait: %.100s", strerror(errno));
603 /* Check if it matches the process we forked. */
605 error("Strange, wait returned pid %d, expected %d", wait_pid, pid);
608 /* We no longer want our SIGCHLD handler to be called. */
609 signal(SIGCHLD, SIG_DFL);
611 /* Check if it exited normally. */
612 if (WIFEXITED(wait_status))
614 /* Yes, normal exit. Get exit status and send it to the client. */
615 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
616 packet_start(SSH_SMSG_EXITSTATUS);
617 packet_put_int(WEXITSTATUS(wait_status));
621 /* Wait for exit confirmation. Note that there might be other
622 packets coming before it; however, the program has already died
623 so we just ignore them. The client is supposed to respond with
624 the confirmation when it receives the exit status. */
628 type = packet_read(&plen);
630 while (type != SSH_CMSG_EXIT_CONFIRMATION);
632 debug("Received exit confirmation.");
636 /* Check if the program terminated due to a signal. */
637 if (WIFSIGNALED(wait_status))
638 packet_disconnect("Command terminated on signal %d.",
639 WTERMSIG(wait_status));
641 /* Some weird exit cause. Just exit. */
642 packet_disconnect("wait returned status %04x.", wait_status);