added telnet_send_sb
diff --git a/README b/README
index 6cc058f..3257b9a 100644
--- a/README
+++ b/README
@@ -218,6 +218,47 @@
   translated.  This should be used if you are attempting to send
   raw data inside a subnegotiation or if you have already manually
   escaped newlines.
+ 
+ void telnet_format_sb(telnet_t *telnet, unsigned char telopt,
+    size_t count, ...);
+  This is a helper function for sending the specially formatted
+  data used in the TTYPE, ENVIRON/NEW-ENVIRON, and MSSP telopt
+  subnegotiations.
+
+  The variadic arguments must be given as a series of pairs of
+  markers and strings.  The markers are different for each telopt;
+  they are defined in libtelnet.h and include:
+
+   /* TTYPE markers */
+   #define TELNET_TTYPE_IS 0
+   #define TELNET_TTYPE_SEND 1
+
+   /* ENVIRON/NEW-ENVIRON markers */
+   #define TELNET_ENVIRON_IS 0
+   #define TELNET_ENVIRON_SEND 1
+   #define TELNET_ENVIRON_INFO 2
+   #define TELNET_ENVIRON_VAR 0
+   #define TELNET_ENVIRON_VALUE 1
+   #define TELNET_ENVIRON_ESC 2
+   #define TELNET_ENVIRON_USERVAR 3
+
+   /* MSSP markers */
+   #define TELNET_MSSP_VAR 1
+   #define TELNET_MSSP_VAL 2
+
+  So to send a TTYPE subnegotiation from the server (just an IS
+  command), you would use:
+
+   telnet_format_sb(&telnet, TELNET_TELOPT_TTYPE, 1,
+     TELNET_TTYPE_SEND);
+
+  The client response for an xterm-compatible terminal would be:
+
+   telnet_format_sb(&telnet, TELNET_TELOPT_TTYPE, 1,
+     TELNET_TTYPE_IS, "xterm");
+
+  For more information on the meaning of the markers and strings,
+  please refer to the specific RFC for the telopt in question.
 
 IId. Event Handling
 
diff --git a/libtelnet.c b/libtelnet.c
index 09ffd8d..695d213 100644
--- a/libtelnet.c
+++ b/libtelnet.c
@@ -1058,6 +1058,31 @@
 	return rs;
 }
 
+/* send formatted subnegotiation data for TTYPE/ENVIRON/NEW-ENVIRON/MSSP */
+void telnet_format_sb(telnet_t *telnet, unsigned char telopt,
+		size_t count, ...) {
+	va_list va;
+	size_t i;
+
+	/* subnegotiation header */
+	telnet_begin_sb(telnet, telopt);
+
+	/* iterate over the arguments pulling out integers and strings */
+	va_start(va, count);
+	for (i = 0; i != count; ++i) {
+		char t;
+		const char* s;
+		t = va_arg(va, int);
+		s = va_arg(va, const char *);
+		telnet_send(telnet, &t, 1);
+		telnet_send(telnet, s, strlen(s));
+	}
+	va_end(va);
+
+	/* footer */
+	telnet_finish_sb(telnet);
+}
+
 /* send ZMP data */
 void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv) {
 	size_t i;
diff --git a/libtelnet.h b/libtelnet.h
index 6a26fdb..52e2e18 100644
--- a/libtelnet.h
+++ b/libtelnet.h
@@ -266,6 +266,10 @@
 extern int telnet_printf2(telnet_t *telnet, const char *fmt, ...)
 		TELNET_GNU_PRINTF(2, 3);
 
+/* send TTYPE/ENVIRON/NEW-ENVIRON/MSSP data */
+extern void telnet_format_sb(telnet_t *telnet, unsigned char telopt,
+		size_t count, ...);
+
 /* send ZMP commands */
 extern void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv);
 extern void telnet_send_zmpv(telnet_t *telnet, ...) TELNET_GNU_SENTINEL;
diff --git a/telnet-client.c b/telnet-client.c
index aa25e4a..9eb58d6 100644
--- a/telnet-client.c
+++ b/telnet-client.c
@@ -116,17 +116,12 @@
 		break;
 	/* respond to particular subnegotiations */
 	case TELNET_EV_SUBNEGOTIATION:
+		/* if they just asked for our terminal type, response with it */
 		/* respond with our terminal type */
-		if (ev->telopt == TELNET_TELOPT_TTYPE) {
-			/* NOTE: we just assume the server sent a legitimate
-			 * sub-negotiation, as there really isn't anything else
-			 * it's allowed to send
-			 */
-			char buffer[64];
-			buffer[0] = 0; /* IS code for RFC 1091 */
-			snprintf(buffer + 1, sizeof(buffer) - 1, "%s", getenv("TERM"));
-			telnet_subnegotiation(telnet, TELNET_TELOPT_TTYPE, buffer,
-					strlen(getenv("TERM")) + 1);
+		if (ev->telopt == TELNET_TELOPT_TTYPE &&
+				ev->argc >= 1 && ev->argv[0][0] == TELNET_TTYPE_SEND) {
+			telnet_format_sb(telnet, TELNET_TELOPT_TTYPE, 1,
+					TELNET_TTYPE_IS, getenv("TERM"));
 		}
 		break;
 	/* error */