1 /*
2 * reply.c
3 * (C)1998-2011 by Marc Huber <Marc.Huber@web.de>
4 * All rights reserved.
5 *
6 * $Id: reply.c,v 1.16 2015/03/14 06:11:27 marc Exp marc $
7 *
8 */
9
10 #include "headers.h"
11 #include <stdarg.h>
12 #include <arpa/telnet.h>
13
14 static const char rcsid[] __attribute__ ((used)) = "$Id: reply.c,v 1.16 2015/03/14 06:11:27 marc Exp marc $";
15
16 /*
17 * For data written to the command channel we need to follow
18 * Telnet NVT conventions.
19 */
20
buffer_reply(struct buffer * b,char * s,size_t len)21 struct buffer *buffer_reply(struct buffer *b, char *s, size_t len)
22 {
23 size_t j = 2 * len;
24 char *a = alloca(j);
25 char *t = a, *se = s + len;
26 DebugIn(DEBUG_PROC);
27
28 for (; s < se; s++) {
29 *t++ = *s;
30 if (*s == '\r')
31 /* <CR> => <CR><NUL> */
32 *t++ = 0, len++;
33 else if ((u_char) * s == IAC)
34 *t++ = IAC, len++;
35 }
36 b = buffer_write(b, a, len);
37 DebugOut(DEBUG_PROC);
38 return b;
39 }
40
replyf(struct context * ctx,char * format,...)41 void replyf(struct context *ctx, char *format, ...)
42 {
43 ssize_t len = 1024, nlen;
44 size_t j = 2 * len;
45 char *tmpbuf;
46
47 DebugIn(DEBUG_PROC);
48
49 again:
50 tmpbuf = alloca(j);
51
52 if (ctx && ctx->cfn > -1) {
53 va_list ap;
54 va_start(ap, format);
55 nlen = vsnprintf(tmpbuf, len, format, ap);
56 va_end(ap);
57 if (len <= nlen) {
58 j = 2 * ++nlen;
59 goto again;
60 }
61 len = nlen;
62
63 if (len > -1) {
64 char *t = tmpbuf + len - 1;
65 char *u = tmpbuf + 2 * len - 1;
66 ssize_t f;
67
68 /* <CR><NL> at the end of the format string is ok */
69 if (len > 1 && ((f = strlen(format)) > 1)
70 && format[f - 2] == '\r' && format[f - 1] == '\n') {
71 *u-- = *t--;
72 *u-- = *t--;
73 }
74
75 for (; t >= tmpbuf; *u-- = *t--)
76 if (*t == '\r')
77 /* <CR> => <CR><NUL> */
78 *u-- = 0, len++;
79 else if ((u_char) * t == IAC)
80 /* <IAC> => <IAC><IAC> */
81 *u-- = IAC, len++;
82 ctx->cbufo = buffer_write(ctx->cbufo, u + 1, len);
83
84 io_set_o(ctx->io, ctx->cfn);
85 }
86 }
87 DebugOut(DEBUG_PROC);
88 }
89
reply(struct context * ctx,char * s)90 void reply(struct context *ctx, char *s)
91 {
92 DebugIn(DEBUG_PROC);
93
94 if (ctx && ctx->cfn > -1) {
95 size_t len = strlen(s);
96 if (len > 1 && s[len - 2] == '\r' && s[len - 1] == '\n') {
97 /* Don't escape <CR><LF> at end of string */
98 ctx->cbufo = buffer_reply(ctx->cbufo, s, len - 2);
99 ctx->cbufo = buffer_write(ctx->cbufo, "\r\n", 2);
100 } else
101 ctx->cbufo = buffer_reply(ctx->cbufo, s, len);
102
103 io_set_o(ctx->io, ctx->cfn);
104 }
105 DebugOut(DEBUG_PROC);
106 }
107