summaryrefslogtreecommitdiffstats
path: root/contrib/telnet
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-04-30 19:52:35 +0000
committerjilles <jilles@FreeBSD.org>2010-04-30 19:52:35 +0000
commit0637e80406802fa3e7dba2dd901b803b17051606 (patch)
treeceb74e0a1f9dfc1915358be873dfed663a90cc66 /contrib/telnet
parent6b22e476a5f920709982cdffed9a2e1b33e847fc (diff)
downloadFreeBSD-src-0637e80406802fa3e7dba2dd901b803b17051606.zip
FreeBSD-src-0637e80406802fa3e7dba2dd901b803b17051606.tar.gz
telnet: Fix infinite loop if local output generates SIGPIPE.
Instead of catching SIGPIPE and jumping out of the signal handler with longjmp, ignore it and handle write errors to the local output by exiting from there. I have changed the error message to mention the local output instead of NetBSD's wrong "Connection closed by foreign host". Write errors to the network were already handled by exiting immediately and this now applies to EPIPE too. The code assumed that SIGPIPE could only be generated by the network connection; if it was generated by the local output, it would longjmp out of the signal handler and write an error message which caused another SIGPIPE. PR: 19773 Obtained from: NetBSD MFC after: 1 week
Diffstat (limited to 'contrib/telnet')
-rw-r--r--contrib/telnet/telnet/commands.c3
-rw-r--r--contrib/telnet/telnet/externs.h1
-rw-r--r--contrib/telnet/telnet/network.c2
-rw-r--r--contrib/telnet/telnet/sys_bsd.c10
-rw-r--r--contrib/telnet/telnet/telnet.c1
-rw-r--r--contrib/telnet/telnet/terminal.c16
6 files changed, 17 insertions, 16 deletions
diff --git a/contrib/telnet/telnet/commands.c b/contrib/telnet/telnet/commands.c
index a64d763..c39b187 100644
--- a/contrib/telnet/telnet/commands.c
+++ b/contrib/telnet/telnet/commands.c
@@ -2491,8 +2491,7 @@ tn(int argc, char *argv[])
env_export("USER");
}
(void) call(status, "status", "notmuch", 0);
- if (setjmp(peerdied) == 0)
- telnet(user);
+ telnet(user);
(void) NetClose(net);
ExitString("Connection closed by foreign host.\n",1);
/*NOTREACHED*/
diff --git a/contrib/telnet/telnet/externs.h b/contrib/telnet/telnet/externs.h
index cfa1aec..e07aebb 100644
--- a/contrib/telnet/telnet/externs.h
+++ b/contrib/telnet/telnet/externs.h
@@ -233,7 +233,6 @@ extern void
SetNetTrace(char *); /* Function to change where debugging goes */
extern jmp_buf
- peerdied,
toplevel; /* For error conditions. */
extern void
diff --git a/contrib/telnet/telnet/network.c b/contrib/telnet/telnet/network.c
index bb75d63..b140d60 100644
--- a/contrib/telnet/telnet/network.c
+++ b/contrib/telnet/telnet/network.c
@@ -158,7 +158,7 @@ netflush(void)
perror(hostname);
(void)NetClose(net);
ring_clear_mark(&netoring);
- longjmp(peerdied, -1);
+ ExitString("Connection closed by foreign host.\n", 1);
/*NOTREACHED*/
}
n = 0;
diff --git a/contrib/telnet/telnet/sys_bsd.c b/contrib/telnet/telnet/sys_bsd.c
index 45ef1e2..9fba74f 100644
--- a/contrib/telnet/telnet/sys_bsd.c
+++ b/contrib/telnet/telnet/sys_bsd.c
@@ -809,14 +809,6 @@ NetNonblockingIO(int fd, int onoff)
*/
/* ARGSUSED */
-static SIG_FUNC_RET
-deadpeer(int sig __unused)
-{
- setcommandmode();
- longjmp(peerdied, -1);
-}
-
-/* ARGSUSED */
SIG_FUNC_RET
intr(int sig __unused)
{
@@ -884,7 +876,7 @@ sys_telnet_init(void)
{
(void) signal(SIGINT, intr);
(void) signal(SIGQUIT, intr2);
- (void) signal(SIGPIPE, deadpeer);
+ (void) signal(SIGPIPE, SIG_IGN);
#ifdef SIGWINCH
(void) signal(SIGWINCH, sendwin);
#endif
diff --git a/contrib/telnet/telnet/telnet.c b/contrib/telnet/telnet/telnet.c
index 28237bd..8c457cf 100644
--- a/contrib/telnet/telnet/telnet.c
+++ b/contrib/telnet/telnet/telnet.c
@@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
#endif
jmp_buf toplevel;
-jmp_buf peerdied;
int flushline;
int linemode;
diff --git a/contrib/telnet/telnet/terminal.c b/contrib/telnet/telnet/terminal.c
index 3dda1c5..596c2b8 100644
--- a/contrib/telnet/telnet/terminal.c
+++ b/contrib/telnet/telnet/terminal.c
@@ -111,7 +111,8 @@ init_terminal(void)
}
/*
- * Send as much data as possible to the terminal.
+ * Send as much data as possible to the terminal, else exits if
+ * it encounters a permanent failure when writing to the tty.
*
* Return value:
* -1: No useful work done, data waiting to go out.
@@ -152,8 +153,19 @@ ttyflush(int drop)
}
ring_consumed(&ttyoring, n);
}
- if (n < 0)
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR) {
+ return -1;
+ } else {
+ ring_consumed(&ttyoring, ring_full_count(&ttyoring));
+ setconnmode(0);
+ setcommandmode();
+ NetClose(net);
+ fprintf(stderr, "Write error on local output.\n");
+ exit(1);
+ }
return -1;
+ }
if (n == n0) {
if (n0)
return -1;
OpenPOWER on IntegriCloud