summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--channels.c49
-rw-r--r--channels.h4
-rw-r--r--clientloop.c3
-rw-r--r--nchan.c15
-rw-r--r--serverloop.c57
-rw-r--r--session.c29
-rw-r--r--session.h4
8 files changed, 94 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index 4a571aa88..f5a13d21d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
120011012
2 - (djm) OpenBSD CVS Sync
3 - markus@cvs.openbsd.org 2001/10/10 22:18:47
4 [channels.c channels.h clientloop.c nchan.c serverloop.c]
5 [session.c session.h]
6 try to keep channels open until an exit-status message is sent.
7 don't kill the login shells if the shells stdin/out/err is closed.
8 this should now work:
9 ssh -2n localhost 'exec > /dev/null 2>&1; sleep 10; exit 5'; echo ?
10
120011010 1120011010
2 - (djm) OpenBSD CVS Sync 12 - (djm) OpenBSD CVS Sync
3 - markus@cvs.openbsd.org 2001/10/04 14:34:16 13 - markus@cvs.openbsd.org 2001/10/04 14:34:16
@@ -6695,4 +6705,4 @@
6695 - Wrote replacements for strlcpy and mkdtemp 6705 - Wrote replacements for strlcpy and mkdtemp
6696 - Released 1.0pre1 6706 - Released 1.0pre1
6697 6707
6698$Id: ChangeLog,v 1.1600 2001/10/10 20:45:43 mouring Exp $ 6708$Id: ChangeLog,v 1.1601 2001/10/12 01:35:04 djm Exp $
diff --git a/channels.c b/channels.c
index 04efd7287..62fd73d74 100644
--- a/channels.c
+++ b/channels.c
@@ -39,7 +39,7 @@
39 */ 39 */
40 40
41#include "includes.h" 41#include "includes.h"
42RCSID("$OpenBSD: channels.c,v 1.139 2001/10/09 21:59:41 markus Exp $"); 42RCSID("$OpenBSD: channels.c,v 1.140 2001/10/10 22:18:47 markus Exp $");
43 43
44#include "ssh.h" 44#include "ssh.h"
45#include "ssh1.h" 45#include "ssh1.h"
@@ -331,10 +331,6 @@ channel_free(Channel *c)
331 debug3("channel_free: status: %s", s); 331 debug3("channel_free: status: %s", s);
332 xfree(s); 332 xfree(s);
333 333
334 if (c->detach_user != NULL) {
335 debug("channel_free: channel %d: detaching channel user", c->self);
336 c->detach_user(c->self, NULL);
337 }
338 if (c->sock != -1) 334 if (c->sock != -1)
339 shutdown(c->sock, SHUT_RDWR); 335 shutdown(c->sock, SHUT_RDWR);
340 channel_close_fds(c); 336 channel_close_fds(c);
@@ -1520,6 +1516,28 @@ channel_handler_init(void)
1520 channel_handler_init_15(); 1516 channel_handler_init_15();
1521} 1517}
1522 1518
1519/* gc dead channels */
1520static void
1521channel_garbage_collect(Channel *c)
1522{
1523 if (c == NULL)
1524 return;
1525 if (c->detach_user != NULL) {
1526 if (!chan_is_dead(c, 0))
1527 return;
1528 debug("channel %d: gc: notify user", c->self);
1529 c->detach_user(c->self, NULL);
1530 /* if we still have a callback */
1531 if (c->detach_user != NULL)
1532 return;
1533 debug("channel %d: gc: user detached", c->self);
1534 }
1535 if (!chan_is_dead(c, 1))
1536 return;
1537 debug("channel %d: garbage collecting", c->self);
1538 channel_free(c);
1539}
1540
1523static void 1541static void
1524channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) 1542channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
1525{ 1543{
@@ -1537,24 +1555,7 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
1537 continue; 1555 continue;
1538 if (ftab[c->type] != NULL) 1556 if (ftab[c->type] != NULL)
1539 (*ftab[c->type])(c, readset, writeset); 1557 (*ftab[c->type])(c, readset, writeset);
1540 if (chan_is_dead(c)) { 1558 channel_garbage_collect(c);
1541 /*
1542 * we have to remove the fd's from the select mask
1543 * before the channels are free'd and the fd's are
1544 * closed
1545 */
1546 if (c->wfd != -1)
1547 FD_CLR(c->wfd, writeset);
1548 if (c->rfd != -1)
1549 FD_CLR(c->rfd, readset);
1550 if (c->efd != -1) {
1551 if (c->extended_usage == CHAN_EXTENDED_READ)
1552 FD_CLR(c->efd, readset);
1553 if (c->extended_usage == CHAN_EXTENDED_WRITE)
1554 FD_CLR(c->efd, writeset);
1555 }
1556 channel_free(c);
1557 }
1558 } 1559 }
1559} 1560}
1560 1561
@@ -1625,7 +1626,7 @@ channel_output_poll()
1625 if (compat20 && 1626 if (compat20 &&
1626 (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { 1627 (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
1627 /* XXX is this true? */ 1628 /* XXX is this true? */
1628 debug2("channel %d: no data after CLOSE", c->self); 1629 debug3("channel %d: will not send data after close", c->self);
1629 continue; 1630 continue;
1630 } 1631 }
1631 1632
diff --git a/channels.h b/channels.h
index 090d2ca6e..89e48009d 100644
--- a/channels.h
+++ b/channels.h
@@ -32,7 +32,7 @@
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35/* RCSID("$OpenBSD: channels.h,v 1.49 2001/10/09 21:59:41 markus Exp $"); */ 35/* RCSID("$OpenBSD: channels.h,v 1.50 2001/10/10 22:18:47 markus Exp $"); */
36 36
37#ifndef CHANNEL_H 37#ifndef CHANNEL_H
38#define CHANNEL_H 38#define CHANNEL_H
@@ -214,7 +214,7 @@ void auth_input_open_request(int, int, void *);
214 214
215/* channel close */ 215/* channel close */
216 216
217int chan_is_dead(Channel *); 217int chan_is_dead(Channel *, int);
218void chan_mark_dead(Channel *); 218void chan_mark_dead(Channel *);
219void chan_init_iostates(Channel *); 219void chan_init_iostates(Channel *);
220void chan_init(void); 220void chan_init(void);
diff --git a/clientloop.c b/clientloop.c
index e6da67d51..43332d1f4 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.82 2001/09/17 20:52:47 markus Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.83 2001/10/10 22:18:47 markus Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -753,6 +753,7 @@ client_channel_closed(int id, void *arg)
753 if (id != session_ident) 753 if (id != session_ident)
754 error("client_channel_closed: id %d != session_ident %d", 754 error("client_channel_closed: id %d != session_ident %d",
755 id, session_ident); 755 id, session_ident);
756 channel_cancel_cleanup(id);
756 session_closed = 1; 757 session_closed = 1;
757 if (in_raw_mode()) 758 if (in_raw_mode())
758 leave_raw_mode(); 759 leave_raw_mode();
diff --git a/nchan.c b/nchan.c
index 91c34dec8..2680f0a68 100644
--- a/nchan.c
+++ b/nchan.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: nchan.c,v 1.31 2001/07/17 21:04:57 markus Exp $"); 26RCSID("$OpenBSD: nchan.c,v 1.32 2001/10/10 22:18:47 markus Exp $");
27 27
28#include "ssh1.h" 28#include "ssh1.h"
29#include "ssh2.h" 29#include "ssh2.h"
@@ -432,7 +432,7 @@ chan_mark_dead(Channel *c)
432} 432}
433 433
434int 434int
435chan_is_dead(Channel *c) 435chan_is_dead(Channel *c, int send)
436{ 436{
437 if (c->type == SSH_CHANNEL_ZOMBIE) { 437 if (c->type == SSH_CHANNEL_ZOMBIE) {
438 debug("channel %d: zombie", c->self); 438 debug("channel %d: zombie", c->self);
@@ -461,7 +461,16 @@ chan_is_dead(Channel *c)
461 "read": "write"); 461 "read": "write");
462 } else { 462 } else {
463 if (!(c->flags & CHAN_CLOSE_SENT)) { 463 if (!(c->flags & CHAN_CLOSE_SENT)) {
464 chan_send_close2(c); 464 if (send) {
465 chan_send_close2(c);
466 } else {
467 /* channel would be dead if we sent a close */
468 if (c->flags & CHAN_CLOSE_RCVD) {
469 debug("channel %d: almost dead",
470 c->self);
471 return 1;
472 }
473 }
465 } 474 }
466 if ((c->flags & CHAN_CLOSE_SENT) && 475 if ((c->flags & CHAN_CLOSE_SENT) &&
467 (c->flags & CHAN_CLOSE_RCVD)) { 476 (c->flags & CHAN_CLOSE_RCVD)) {
diff --git a/serverloop.c b/serverloop.c
index 8a82af55b..983fe7443 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: serverloop.c,v 1.81 2001/10/09 21:59:41 markus Exp $"); 38RCSID("$OpenBSD: serverloop.c,v 1.82 2001/10/10 22:18:47 markus Exp $");
39 39
40#include "xmalloc.h" 40#include "xmalloc.h"
41#include "packet.h" 41#include "packet.h"
@@ -208,9 +208,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
208 max_time_milliseconds = options.client_alive_interval * 1000; 208 max_time_milliseconds = options.client_alive_interval * 1000;
209 } 209 }
210 210
211 /* When select fails we restart from here. */
212retry_select:
213
214 /* Allocate and update select() masks for channel descriptors. */ 211 /* Allocate and update select() masks for channel descriptors. */
215 channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); 212 channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0);
216 213
@@ -275,12 +272,11 @@ retry_select:
275 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); 272 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
276 273
277 if (ret == -1) { 274 if (ret == -1) {
275 memset(*readsetp, 0, *maxfdp);
276 memset(*writesetp, 0, *maxfdp);
278 if (errno != EINTR) 277 if (errno != EINTR)
279 error("select: %.100s", strerror(errno)); 278 error("select: %.100s", strerror(errno));
280 else 279 } else if (ret == 0 && client_alive_scheduled)
281 goto retry_select;
282 }
283 if (ret == 0 && client_alive_scheduled)
284 client_alive_check(); 280 client_alive_check();
285} 281}
286 282
@@ -668,13 +664,30 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
668 /* NOTREACHED */ 664 /* NOTREACHED */
669} 665}
670 666
667static void
668collect_children(void)
669{
670 pid_t pid;
671 sigset_t oset, nset;
672 int status;
673
674 /* block SIGCHLD while we check for dead children */
675 sigemptyset(&nset);
676 sigaddset(&nset, SIGCHLD);
677 sigprocmask(SIG_BLOCK, &nset, &oset);
678 if (child_terminated) {
679 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
680 session_close_by_pid(pid, status);
681 child_terminated = 0;
682 }
683 sigprocmask(SIG_SETMASK, &oset, NULL);
684}
685
671void 686void
672server_loop2(Authctxt *authctxt) 687server_loop2(Authctxt *authctxt)
673{ 688{
674 fd_set *readset = NULL, *writeset = NULL; 689 fd_set *readset = NULL, *writeset = NULL;
675 int rekeying = 0, max_fd, status, nalloc = 0; 690 int rekeying = 0, max_fd, nalloc = 0;
676 pid_t pid;
677 sigset_t oset, nset;
678 691
679 debug("Entering interactive session for SSH2."); 692 debug("Entering interactive session for SSH2.");
680 693
@@ -698,16 +711,7 @@ server_loop2(Authctxt *authctxt)
698 wait_until_can_do_something(&readset, &writeset, &max_fd, 711 wait_until_can_do_something(&readset, &writeset, &max_fd,
699 &nalloc, 0); 712 &nalloc, 0);
700 713
701 /* block SIGCHLD while we check for dead children */ 714 collect_children();
702 sigemptyset(&nset);
703 sigaddset(&nset, SIGCHLD);
704 sigprocmask(SIG_BLOCK, &nset, &oset);
705 if (child_terminated) {
706 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
707 session_close_by_pid(pid, status);
708 child_terminated = 0;
709 }
710 sigprocmask(SIG_SETMASK, &oset, NULL);
711 if (!rekeying) 715 if (!rekeying)
712 channel_after_select(readset, writeset); 716 channel_after_select(readset, writeset);
713 process_input(readset); 717 process_input(readset);
@@ -715,6 +719,8 @@ server_loop2(Authctxt *authctxt)
715 break; 719 break;
716 process_output(writeset); 720 process_output(writeset);
717 } 721 }
722 collect_children();
723
718 if (readset) 724 if (readset)
719 xfree(readset); 725 xfree(readset);
720 if (writeset) 726 if (writeset)
@@ -723,13 +729,8 @@ server_loop2(Authctxt *authctxt)
723 /* free all channels, no more reads and writes */ 729 /* free all channels, no more reads and writes */
724 channel_free_all(); 730 channel_free_all();
725 731
726 /* collect remaining dead children, XXX not necessary? */ 732 /* free remaining sessions, e.g. remove wtmp entries */
727 mysignal(SIGCHLD, SIG_DFL); 733 session_destroy_all();
728 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
729 session_close_by_pid(pid, status);
730
731 /* close remaining sessions, e.g remove wtmp entries */
732 session_close_all();
733} 734}
734 735
735static void 736static void
diff --git a/session.c b/session.c
index 0d6ebdaea..6ba2e7c77 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.106 2001/10/09 21:59:41 markus Exp $"); 36RCSID("$OpenBSD: session.c,v 1.107 2001/10/10 22:18:47 markus Exp $");
37 37
38#include "ssh.h" 38#include "ssh.h"
39#include "ssh1.h" 39#include "ssh1.h"
@@ -1958,36 +1958,29 @@ session_close_by_channel(int id, void *arg)
1958{ 1958{
1959 Session *s = session_by_channel(id); 1959 Session *s = session_by_channel(id);
1960 if (s == NULL) { 1960 if (s == NULL) {
1961 debug("session_close_by_channel: no session for channel %d", id); 1961 debug("session_close_by_channel: no session for id %d", id);
1962 return; 1962 return;
1963 } 1963 }
1964 /* disconnect channel */ 1964 debug("session_close_by_channel: channel %d child %d", id, s->pid);
1965 channel_cancel_cleanup(s->chanid);
1966 s->chanid = -1;
1967
1968 debug("session_close_by_channel: channel %d kill %d", id, s->pid);
1969 if (s->pid != 0) { 1965 if (s->pid != 0) {
1970 /* notify child */ 1966 /* delay detach */
1971 if (kill(s->pid, SIGHUP) < 0) 1967 debug("session_close_by_channel: channel %d: has child", id);
1972 error("session_close_by_channel: kill %d: %s", 1968 return;
1973 s->pid, strerror(errno));
1974 } 1969 }
1970 /* detach by removing callback */
1971 channel_cancel_cleanup(s->chanid);
1972 s->chanid = -1;
1975 session_close(s); 1973 session_close(s);
1976} 1974}
1977 1975
1978void 1976void
1979session_close_all(void) 1977session_destroy_all(void)
1980{ 1978{
1981 int i; 1979 int i;
1982 for(i = 0; i < MAX_SESSIONS; i++) { 1980 for(i = 0; i < MAX_SESSIONS; i++) {
1983 Session *s = &sessions[i]; 1981 Session *s = &sessions[i];
1984 if (s->used) { 1982 if (s->used)
1985 if (s->chanid != -1) {
1986 channel_cancel_cleanup(s->chanid);
1987 s->chanid = -1;
1988 }
1989 session_close(s); 1983 session_close(s);
1990 }
1991 } 1984 }
1992} 1985}
1993 1986
diff --git a/session.h b/session.h
index d2b0d9364..6d5b8e699 100644
--- a/session.h
+++ b/session.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.h,v 1.12 2001/10/09 21:59:41 markus Exp $ */ 1/* $OpenBSD: session.h,v 1.13 2001/10/10 22:18:47 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -32,6 +32,6 @@ int session_open(Authctxt*, int);
32void session_input_channel_req(int, void *); 32void session_input_channel_req(int, void *);
33void session_close_by_pid(pid_t, int); 33void session_close_by_pid(pid_t, int);
34void session_close_by_channel(int, void *); 34void session_close_by_channel(int, void *);
35void session_close_all(void); 35void session_destroy_all(void);
36 36
37#endif 37#endif