diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/clientloop.c b/clientloop.c index 5608bcc2e..de7979366 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.221 2010/06/25 23:15:36 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.222 2010/07/19 09:15:12 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -145,6 +145,9 @@ static volatile sig_atomic_t received_signal = 0; | |||
145 | /* Flag indicating whether the user's terminal is in non-blocking mode. */ | 145 | /* Flag indicating whether the user's terminal is in non-blocking mode. */ |
146 | static int in_non_blocking_mode = 0; | 146 | static int in_non_blocking_mode = 0; |
147 | 147 | ||
148 | /* Time when backgrounded control master using ControlPersist should exit */ | ||
149 | static time_t control_persist_exit_time = 0; | ||
150 | |||
148 | /* Common data for the client loop code. */ | 151 | /* Common data for the client loop code. */ |
149 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 152 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
150 | static int escape_char1; /* Escape character. (proto1 only) */ | 153 | static int escape_char1; /* Escape character. (proto1 only) */ |
@@ -252,6 +255,34 @@ get_current_time(void) | |||
252 | return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; | 255 | return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; |
253 | } | 256 | } |
254 | 257 | ||
258 | /* | ||
259 | * Sets control_persist_exit_time to the absolute time when the | ||
260 | * backgrounded control master should exit due to expiry of the | ||
261 | * ControlPersist timeout. Sets it to 0 if we are not a backgrounded | ||
262 | * control master process, or if there is no ControlPersist timeout. | ||
263 | */ | ||
264 | static void | ||
265 | set_control_persist_exit_time(void) | ||
266 | { | ||
267 | if (muxserver_sock == -1 || !options.control_persist | ||
268 | || options.control_persist_timeout == 0) | ||
269 | /* not using a ControlPersist timeout */ | ||
270 | control_persist_exit_time = 0; | ||
271 | else if (channel_still_open()) { | ||
272 | /* some client connections are still open */ | ||
273 | if (control_persist_exit_time > 0) | ||
274 | debug2("%s: cancel scheduled exit", __func__); | ||
275 | control_persist_exit_time = 0; | ||
276 | } else if (control_persist_exit_time <= 0) { | ||
277 | /* a client connection has recently closed */ | ||
278 | control_persist_exit_time = time(NULL) + | ||
279 | (time_t)options.control_persist_timeout; | ||
280 | debug2("%s: schedule exit in %d seconds", __func__, | ||
281 | options.control_persist_timeout); | ||
282 | } | ||
283 | /* else we are already counting down to the timeout */ | ||
284 | } | ||
285 | |||
255 | #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" | 286 | #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
256 | void | 287 | void |
257 | client_x11_get_proto(const char *display, const char *xauth_path, | 288 | client_x11_get_proto(const char *display, const char *xauth_path, |
@@ -533,6 +564,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
533 | int *maxfdp, u_int *nallocp, int rekeying) | 564 | int *maxfdp, u_int *nallocp, int rekeying) |
534 | { | 565 | { |
535 | struct timeval tv, *tvp; | 566 | struct timeval tv, *tvp; |
567 | int timeout_secs; | ||
536 | int ret; | 568 | int ret; |
537 | 569 | ||
538 | /* Add any selections by the channel mechanism. */ | 570 | /* Add any selections by the channel mechanism. */ |
@@ -576,16 +608,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
576 | /* | 608 | /* |
577 | * Wait for something to happen. This will suspend the process until | 609 | * Wait for something to happen. This will suspend the process until |
578 | * some selected descriptor can be read, written, or has some other | 610 | * some selected descriptor can be read, written, or has some other |
579 | * event pending. | 611 | * event pending, or a timeout expires. |
580 | */ | 612 | */ |
581 | 613 | ||
582 | if (options.server_alive_interval == 0 || !compat20) | 614 | timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ |
615 | if (options.server_alive_interval > 0 && compat20) | ||
616 | timeout_secs = options.server_alive_interval; | ||
617 | set_control_persist_exit_time(); | ||
618 | if (control_persist_exit_time > 0) { | ||
619 | timeout_secs = MIN(timeout_secs, | ||
620 | control_persist_exit_time - time(NULL)); | ||
621 | if (timeout_secs < 0) | ||
622 | timeout_secs = 0; | ||
623 | } | ||
624 | if (timeout_secs == INT_MAX) | ||
583 | tvp = NULL; | 625 | tvp = NULL; |
584 | else { | 626 | else { |
585 | tv.tv_sec = options.server_alive_interval; | 627 | tv.tv_sec = timeout_secs; |
586 | tv.tv_usec = 0; | 628 | tv.tv_usec = 0; |
587 | tvp = &tv; | 629 | tvp = &tv; |
588 | } | 630 | } |
631 | |||
589 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); | 632 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); |
590 | if (ret < 0) { | 633 | if (ret < 0) { |
591 | char buf[100]; | 634 | char buf[100]; |
@@ -1478,6 +1521,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1478 | */ | 1521 | */ |
1479 | if (FD_ISSET(connection_out, writeset)) | 1522 | if (FD_ISSET(connection_out, writeset)) |
1480 | packet_write_poll(); | 1523 | packet_write_poll(); |
1524 | |||
1525 | /* | ||
1526 | * If we are a backgrounded control master, and the | ||
1527 | * timeout has expired without any active client | ||
1528 | * connections, then quit. | ||
1529 | */ | ||
1530 | if (control_persist_exit_time > 0) { | ||
1531 | if (time(NULL) >= control_persist_exit_time) { | ||
1532 | debug("ControlPersist timeout expired"); | ||
1533 | break; | ||
1534 | } | ||
1535 | } | ||
1481 | } | 1536 | } |
1482 | if (readset) | 1537 | if (readset) |
1483 | xfree(readset); | 1538 | xfree(readset); |