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, read as much as is available and then exit. */
273 if (child_terminated)
274 if (max_time_milliseconds == 0)
275 max_time_milliseconds = 100;
277 if (max_time_milliseconds == 0)
281 tv.tv_sec = max_time_milliseconds / 1000;
282 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
286 /* Wait for something to happen, or the timeout to expire. */
287 ret = select(max_fd + 1, readset, writeset, NULL, tvp);
292 error("select: %.100s", strerror(errno));
298 /* Processes input from the client and the program. Input data is stored
299 in buffers and processed later. */
301 void process_input(fd_set *readset)
306 /* Read and buffer any input data from the client. */
307 if (FD_ISSET(connection_in, readset))
309 len = read(connection_in, buf, sizeof(buf));
311 fatal("Connection closed by remote host.");
313 /* There is a kernel bug on Solaris that causes select to sometimes
314 wake up even though there is no data available. */
315 if (len < 0 && errno == EAGAIN)
319 fatal("Read error from remote host: %.100s", strerror(errno));
321 /* Buffer any received data. */
322 packet_process_incoming(buf, len);
325 /* Read and buffer any available stdout data from the program. */
326 if (!fdout_eof && FD_ISSET(fdout, readset))
328 len = read(fdout, buf, sizeof(buf));
333 buffer_append(&stdout_buffer, buf, len);
338 /* Read and buffer any available stderr data from the program. */
339 if (!fderr_eof && FD_ISSET(fderr, readset))
341 len = read(fderr, buf, sizeof(buf));
345 buffer_append(&stderr_buffer, buf, len);
349 /* Sends data from internal buffers to client program stdin. */
351 void process_output(fd_set *writeset)
355 /* Write buffered data to program stdin. */
356 if (fdin != -1 && FD_ISSET(fdin, writeset))
358 len = write(fdin, buffer_ptr(&stdin_buffer),
359 buffer_len(&stdin_buffer));
368 shutdown(fdin, SHUT_WR); /* We will no longer send. */
374 /* Successful write. Consume the data from the buffer. */
375 buffer_consume(&stdin_buffer, len);
376 /* Update the count of bytes written to the program. */
381 /* Send any buffered packet data to the client. */
382 if (FD_ISSET(connection_out, writeset))
386 /* Wait until all buffered output has been sent to the client.
387 This is used when the program terminates. */
391 /* Send any buffered stdout data to the client. */
392 if (buffer_len(&stdout_buffer) > 0)
394 packet_start(SSH_SMSG_STDOUT_DATA);
395 packet_put_string(buffer_ptr(&stdout_buffer),
396 buffer_len(&stdout_buffer));
398 /* Update the count of sent bytes. */
399 stdout_bytes += buffer_len(&stdout_buffer);
402 /* Send any buffered stderr data to the client. */
403 if (buffer_len(&stderr_buffer) > 0)
405 packet_start(SSH_SMSG_STDERR_DATA);
406 packet_put_string(buffer_ptr(&stderr_buffer),
407 buffer_len(&stderr_buffer));
409 /* Update the count of sent bytes. */
410 stderr_bytes += buffer_len(&stderr_buffer);
413 /* Wait until all buffered data has been written to the client. */
417 /* Performs the interactive session. This handles data transmission between
418 the client and the program. Note that the notion of stdin, stdout, and
419 stderr in this function is sort of reversed: this function writes to
420 stdin (of the child program), and reads from stdout and stderr (of the
423 void server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
425 int wait_status, wait_pid; /* Status and pid returned by wait(). */
426 int waiting_termination = 0; /* Have displayed waiting close message. */
427 unsigned int max_time_milliseconds;
428 unsigned int previous_stdout_buffer_bytes;
429 unsigned int stdout_buffer_bytes;
432 debug("Entering interactive session.");
434 /* Initialize the SIGCHLD kludge. */
436 child_terminated = 0;
437 signal(SIGCHLD, sigchld_handler);
439 /* Initialize our global variables. */
443 connection_in = packet_get_connection_in();
444 connection_out = packet_get_connection_out();
446 previous_stdout_buffer_bytes = 0;
448 /* Set approximate I/O buffer size. */
449 if (packet_is_interactive())
452 buffer_high = 64 * 1024;
454 /* Initialize max_fd to the maximum of the known file descriptors. */
458 if (fderr != -1 && fderr > max_fd)
460 if (connection_in > max_fd)
461 max_fd = connection_in;
462 if (connection_out > max_fd)
463 max_fd = connection_out;
465 /* Initialize Initialize buffers. */
466 buffer_init(&stdin_buffer);
467 buffer_init(&stdout_buffer);
468 buffer_init(&stderr_buffer);
470 /* If we have no separate fderr (which is the case when we have a pty - there
471 we cannot make difference between data sent to stdout and stderr),
472 indicate that we have seen an EOF from stderr. This way we don\'t
473 need to check the descriptor everywhere. */
477 /* Main loop of the server for the interactive session mode. */
480 fd_set readset, writeset;
482 /* Process buffered packets from the client. */
483 process_buffered_input_packets();
485 /* If we have received eof, and there is no more pending input data,
486 cause a real eof by closing fdin. */
487 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0)
495 shutdown(fdin, SHUT_WR); /* We will no longer send. */
500 /* Make packets from buffered stderr data to send to the client. */
501 make_packets_from_stderr_data();
503 /* Make packets from buffered stdout data to send to the client.
504 If there is very little to send, this arranges to not send them
505 now, but to wait a short while to see if we are getting more data.
506 This is necessary, as some systems wake up readers from a pty after
507 each separate character. */
508 max_time_milliseconds = 0;
509 stdout_buffer_bytes = buffer_len(&stdout_buffer);
510 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
511 stdout_buffer_bytes != previous_stdout_buffer_bytes)
512 max_time_milliseconds = 10; /* try again after a while */
514 make_packets_from_stdout_data(); /* Send it now. */
515 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
517 /* Send channel data to the client. */
518 if (packet_not_very_much_data_to_write())
519 channel_output_poll();
521 /* Bail out of the loop if the program has closed its output descriptors,
522 and we have no more data to send to the client, and there is no
523 pending buffered data. */
524 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
525 buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0)
527 if (!channel_still_open())
529 if (!waiting_termination)
532 "Waiting for forwarded connections to terminate...\r\n";
534 waiting_termination = 1;
535 buffer_append(&stderr_buffer, s, strlen(s));
537 /* Display list of open channels. */
538 cp = channel_open_message();
539 buffer_append(&stderr_buffer, cp, strlen(cp));
544 /* Sleep in select() until we can do something. */
545 wait_until_can_do_something(&readset, &writeset,
546 max_time_milliseconds);
548 /* Process any channel events. */
549 channel_after_select(&readset, &writeset);
551 /* Process input from the client and from program stdout/stderr. */
552 process_input(&readset);
554 /* Process output to the client and to program stdin. */
555 process_output(&writeset);
559 /* Cleanup and termination code. */
561 /* Wait until all output has been sent to the client. */
564 debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
565 stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
567 /* Free and clear the buffers. */
568 buffer_free(&stdin_buffer);
569 buffer_free(&stdout_buffer);
570 buffer_free(&stderr_buffer);
572 /* Close the file descriptors. */
585 /* Stop listening for channels; this removes unix domain sockets. */
586 channel_stop_listening();
588 /* Wait for the child to exit. Get its exit status. */
589 wait_pid = wait(&wait_status);
592 /* It is possible that the wait was handled by SIGCHLD handler. This
593 may result in either: this call returning with EINTR, or: this
594 call returning ECHILD. */
595 if (child_terminated)
596 wait_status = child_wait_status;
598 packet_disconnect("wait: %.100s", strerror(errno));
602 /* Check if it matches the process we forked. */
604 error("Strange, wait returned pid %d, expected %d", wait_pid, pid);
607 /* We no longer want our SIGCHLD handler to be called. */
608 signal(SIGCHLD, SIG_DFL);
610 /* Check if it exited normally. */
611 if (WIFEXITED(wait_status))
613 /* Yes, normal exit. Get exit status and send it to the client. */
614 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
615 packet_start(SSH_SMSG_EXITSTATUS);
616 packet_put_int(WEXITSTATUS(wait_status));
620 /* Wait for exit confirmation. Note that there might be other
621 packets coming before it; however, the program has already died
622 so we just ignore them. The client is supposed to respond with
623 the confirmation when it receives the exit status. */
627 type = packet_read(&plen);
629 while (type != SSH_CMSG_EXIT_CONFIRMATION);
631 debug("Received exit confirmation.");
635 /* Check if the program terminated due to a signal. */
636 if (WIFSIGNALED(wait_status))
637 packet_disconnect("Command terminated on signal %d.",
638 WTERMSIG(wait_status));
640 /* Some weird exit cause. Just exit. */
641 packet_disconnect("wait returned status %04x.", wait_status);