1202719Sgabor/*	$OpenBSD: inout.c,v 1.15 2009/10/27 23:59:37 deraadt Exp $	*/
2202719Sgabor
3202719Sgabor/*
4202719Sgabor * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5202719Sgabor *
6202719Sgabor * Permission to use, copy, modify, and distribute this software for any
7202719Sgabor * purpose with or without fee is hereby granted, provided that the above
8202719Sgabor * copyright notice and this permission notice appear in all copies.
9202719Sgabor *
10202719Sgabor * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11202719Sgabor * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12202719Sgabor * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13202719Sgabor * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14202719Sgabor * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15202719Sgabor * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16202719Sgabor * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17202719Sgabor */
18202719Sgabor
19202719Sgabor#include <sys/cdefs.h>
20202719Sgabor__FBSDID("$FreeBSD$");
21202719Sgabor
22202719Sgabor#include <openssl/ssl.h>
23202719Sgabor#include <ctype.h>
24202719Sgabor#include <err.h>
25202719Sgabor#include <string.h>
26202719Sgabor
27202719Sgabor#include "extern.h"
28202719Sgabor
29202719Sgabor#define MAX_CHARS_PER_LINE 68
30202719Sgabor
31202719Sgaborstatic int	 lastchar;
32202719Sgaborstatic int	 charcount;
33202719Sgabor
34202719Sgaborstatic int	 src_getcharstream(struct source *);
35202719Sgaborstatic void	 src_ungetcharstream(struct source *);
36202719Sgaborstatic char	*src_getlinestream(struct source *);
37202719Sgaborstatic int	 src_getcharstring(struct source *);
38202719Sgaborstatic void	 src_ungetcharstring(struct source *);
39202719Sgaborstatic char	*src_getlinestring(struct source *);
40202719Sgaborstatic void	 src_freestring(struct source *);
41202719Sgaborstatic void	 flushwrap(FILE *);
42202719Sgaborstatic void	 putcharwrap(FILE *, int);
43202719Sgaborstatic void	 printwrap(FILE *, const char *);
44202719Sgaborstatic char	*get_digit(u_long, int, u_int);
45202719Sgabor
46202719Sgaborstatic struct vtable stream_vtable = {
47202719Sgabor	src_getcharstream,
48202719Sgabor	src_ungetcharstream,
49202719Sgabor	src_getlinestream,
50202719Sgabor	NULL
51202719Sgabor};
52202719Sgabor
53202719Sgaborstatic struct vtable string_vtable = {
54202719Sgabor	src_getcharstring,
55202719Sgabor	src_ungetcharstring,
56202719Sgabor	src_getlinestring,
57202719Sgabor	src_freestring
58202719Sgabor};
59202719Sgabor
60202719Sgaborvoid
61202719Sgaborsrc_setstream(struct source *src, FILE *stream)
62202719Sgabor{
63202719Sgabor
64202719Sgabor	src->u.stream = stream;
65202719Sgabor	src->vtable = &stream_vtable;
66202719Sgabor}
67202719Sgabor
68202719Sgaborvoid
69202719Sgaborsrc_setstring(struct source *src, char *p)
70202719Sgabor{
71202719Sgabor
72202719Sgabor	src->u.string.buf = (u_char *)p;
73202719Sgabor	src->u.string.pos = 0;
74202719Sgabor	src->vtable = &string_vtable;
75202719Sgabor}
76202719Sgabor
77202719Sgaborstatic int
78202719Sgaborsrc_getcharstream(struct source *src)
79202719Sgabor{
80202719Sgabor
81202719Sgabor	return (src->lastchar = getc(src->u.stream));
82202719Sgabor}
83202719Sgabor
84202719Sgaborstatic void
85202719Sgaborsrc_ungetcharstream(struct source *src)
86202719Sgabor{
87202719Sgabor
88202719Sgabor	ungetc(src->lastchar, src->u.stream);
89202719Sgabor}
90202719Sgabor
91202719Sgaborstatic char *
92202719Sgaborsrc_getlinestream(struct source *src)
93202719Sgabor{
94203443Sgabor	char buf[BUFSIZ];
95202719Sgabor
96202719Sgabor	if (fgets(buf, BUFSIZ, src->u.stream) == NULL)
97202719Sgabor		return (bstrdup(""));
98202719Sgabor	return bstrdup(buf);
99202719Sgabor}
100202719Sgabor
101202719Sgaborstatic int
102202719Sgaborsrc_getcharstring(struct source *src)
103202719Sgabor{
104202719Sgabor
105202719Sgabor	src->lastchar = src->u.string.buf[src->u.string.pos];
106202719Sgabor	if (src->lastchar == '\0')
107202719Sgabor		return (EOF);
108202719Sgabor	else {
109202719Sgabor		src->u.string.pos++;
110202719Sgabor		return (src->lastchar);
111202719Sgabor	}
112202719Sgabor}
113202719Sgabor
114202719Sgaborstatic void
115202719Sgaborsrc_ungetcharstring(struct source *src)
116202719Sgabor{
117202719Sgabor
118202719Sgabor	if (src->u.string.pos > 0) {
119202719Sgabor		if (src->lastchar != '\0')
120202719Sgabor			--src->u.string.pos;
121202719Sgabor	}
122202719Sgabor}
123202719Sgabor
124202719Sgaborstatic char *
125202719Sgaborsrc_getlinestring(struct source *src)
126202719Sgabor{
127203443Sgabor	char buf[BUFSIZ];
128203443Sgabor	int i, ch;
129202719Sgabor
130202719Sgabor	i = 0;
131202719Sgabor	while (i < BUFSIZ-1) {
132202719Sgabor		ch = src_getcharstring(src);
133202719Sgabor		if (ch == EOF)
134202719Sgabor			break;
135202719Sgabor		buf[i++] = ch;
136202719Sgabor		if (ch == '\n')
137202719Sgabor			break;
138202719Sgabor	}
139202719Sgabor	buf[i] = '\0';
140202719Sgabor	return (bstrdup(buf));
141202719Sgabor}
142202719Sgabor
143202719Sgaborstatic void
144202719Sgaborsrc_freestring(struct source *src)
145202719Sgabor{
146202719Sgabor
147202719Sgabor	free(src->u.string.buf);
148202719Sgabor}
149202719Sgabor
150202719Sgaborstatic void
151202719Sgaborflushwrap(FILE *f)
152202719Sgabor{
153202719Sgabor
154202719Sgabor	if (lastchar != -1)
155202719Sgabor		putc(lastchar, f);
156202719Sgabor}
157202719Sgabor
158202719Sgaborstatic void
159202719Sgaborputcharwrap(FILE *f, int ch)
160202719Sgabor{
161202719Sgabor
162202719Sgabor	if (charcount >= MAX_CHARS_PER_LINE) {
163202719Sgabor		charcount = 0;
164202719Sgabor		fputs("\\\n", f);
165202719Sgabor	}
166202719Sgabor	if (lastchar != -1) {
167202719Sgabor		charcount++;
168202719Sgabor		putc(lastchar, f);
169202719Sgabor	}
170202719Sgabor	lastchar = ch;
171202719Sgabor}
172202719Sgabor
173202719Sgaborstatic void
174202719Sgaborprintwrap(FILE *f, const char *p)
175202719Sgabor{
176203443Sgabor	char *q;
177203443Sgabor	char buf[12];
178202719Sgabor
179203443Sgabor	q = buf;
180202719Sgabor	strlcpy(buf, p, sizeof(buf));
181202719Sgabor	while (*q)
182202719Sgabor		putcharwrap(f, *q++);
183202719Sgabor}
184202719Sgabor
185202719Sgaborstruct number *
186202719Sgaborreadnumber(struct source *src, u_int base)
187202719Sgabor{
188203443Sgabor	struct number *n;
189203443Sgabor	BN_ULONG v;
190203443Sgabor	u_int i;
191203443Sgabor	int ch;
192203443Sgabor	bool dot = false, sign = false;
193202719Sgabor
194202719Sgabor	n = new_number();
195202719Sgabor	bn_check(BN_zero(n->number));
196202719Sgabor
197202719Sgabor	while ((ch = (*src->vtable->readchar)(src)) != EOF) {
198202719Sgabor
199202719Sgabor		if ('0' <= ch && ch <= '9')
200202719Sgabor			v = ch - '0';
201202719Sgabor		else if ('A' <= ch && ch <= 'F')
202202719Sgabor			v = ch - 'A' + 10;
203202719Sgabor		else if (ch == '_') {
204202719Sgabor			sign = true;
205202719Sgabor			continue;
206202719Sgabor		} else if (ch == '.') {
207202719Sgabor			if (dot)
208202719Sgabor				break;
209202719Sgabor			dot = true;
210202719Sgabor			continue;
211202719Sgabor		} else {
212202719Sgabor			(*src->vtable->unreadchar)(src);
213202719Sgabor			break;
214202719Sgabor		}
215202719Sgabor		if (dot)
216202719Sgabor			n->scale++;
217202719Sgabor
218202719Sgabor		bn_check(BN_mul_word(n->number, base));
219202719Sgabor
220202719Sgabor#if 0
221202719Sgabor		/* work around a bug in BN_add_word: 0 += 0 is buggy.... */
222202719Sgabor		if (v > 0)
223202719Sgabor#endif
224202719Sgabor			bn_check(BN_add_word(n->number, v));
225202719Sgabor	}
226202719Sgabor	if (base != 10) {
227202719Sgabor		scale_number(n->number, n->scale);
228202719Sgabor		for (i = 0; i < n->scale; i++)
229202719Sgabor			BN_div_word(n->number, base);
230202719Sgabor	}
231202719Sgabor	if (sign)
232202719Sgabor		negate(n);
233202719Sgabor	return (n);
234202719Sgabor}
235202719Sgabor
236202719Sgaborchar *
237202719Sgaborread_string(struct source *src)
238202719Sgabor{
239203443Sgabor	char *p;
240203443Sgabor	int count, ch, i, new_sz, sz;
241203443Sgabor	bool escape;
242202719Sgabor
243202719Sgabor	escape = false;
244202719Sgabor	count = 1;
245202719Sgabor	i = 0;
246202719Sgabor	sz = 15;
247202719Sgabor	p = bmalloc(sz + 1);
248202719Sgabor
249202719Sgabor	while ((ch = (*src->vtable->readchar)(src)) != EOF) {
250202719Sgabor		if (!escape) {
251202719Sgabor			if (ch == '[')
252202719Sgabor				count++;
253202719Sgabor			else if (ch == ']')
254202719Sgabor				count--;
255202719Sgabor			if (count == 0)
256202719Sgabor				break;
257202719Sgabor		}
258202719Sgabor		if (ch == '\\' && !escape)
259202719Sgabor			escape = true;
260202719Sgabor		else {
261202719Sgabor			escape = false;
262202719Sgabor			if (i == sz) {
263202719Sgabor				new_sz = sz * 2;
264202719Sgabor				p = brealloc(p, new_sz + 1);
265202719Sgabor				sz = new_sz;
266202719Sgabor			}
267202719Sgabor			p[i++] = ch;
268202719Sgabor		}
269202719Sgabor	}
270202719Sgabor	p[i] = '\0';
271202719Sgabor	return (p);
272202719Sgabor}
273202719Sgabor
274202719Sgaborstatic char *
275202719Sgaborget_digit(u_long num, int digits, u_int base)
276202719Sgabor{
277203443Sgabor	char *p;
278202719Sgabor
279202719Sgabor	if (base <= 16) {
280202719Sgabor		p = bmalloc(2);
281202719Sgabor		p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
282202719Sgabor		p[1] = '\0';
283202719Sgabor	} else {
284202719Sgabor		if (asprintf(&p, "%0*lu", digits, num) == -1)
285202719Sgabor			err(1, NULL);
286202719Sgabor	}
287202719Sgabor	return (p);
288202719Sgabor}
289202719Sgabor
290202719Sgaborvoid
291202719Sgaborprintnumber(FILE *f, const struct number *b, u_int base)
292202719Sgabor{
293203443Sgabor	struct number *fract_part, *int_part;
294203443Sgabor	struct stack stack;
295203443Sgabor	char *p;
296203443Sgabor	char buf[11];
297203443Sgabor	size_t sz;
298203443Sgabor	unsigned int i;
299203443Sgabor	int digits;
300202719Sgabor
301202719Sgabor	charcount = 0;
302202719Sgabor	lastchar = -1;
303202719Sgabor	if (BN_is_zero(b->number))
304202719Sgabor		putcharwrap(f, '0');
305202719Sgabor
306202719Sgabor	int_part = new_number();
307202719Sgabor	fract_part = new_number();
308202719Sgabor	fract_part->scale = b->scale;
309202719Sgabor
310202719Sgabor	if (base <= 16)
311202719Sgabor		digits = 1;
312202719Sgabor	else {
313202719Sgabor		digits = snprintf(buf, sizeof(buf), "%u", base-1);
314202719Sgabor	}
315202719Sgabor	split_number(b, int_part->number, fract_part->number);
316202719Sgabor
317202719Sgabor	i = 0;
318202719Sgabor	stack_init(&stack);
319202719Sgabor	while (!BN_is_zero(int_part->number)) {
320202719Sgabor		BN_ULONG rem = BN_div_word(int_part->number, base);
321202719Sgabor		stack_pushstring(&stack, get_digit(rem, digits, base));
322202719Sgabor		i++;
323202719Sgabor	}
324202719Sgabor	sz = i;
325202719Sgabor	if (BN_cmp(b->number, &zero) < 0)
326202719Sgabor		putcharwrap(f, '-');
327202719Sgabor	for (i = 0; i < sz; i++) {
328202719Sgabor		p = stack_popstring(&stack);
329202719Sgabor		if (base > 16)
330202719Sgabor			putcharwrap(f, ' ');
331202719Sgabor		printwrap(f, p);
332202719Sgabor		free(p);
333202719Sgabor	}
334202719Sgabor	stack_clear(&stack);
335202719Sgabor	if (b->scale > 0) {
336203443Sgabor		struct number *num_base;
337203443Sgabor		BIGNUM mult, stop;
338202719Sgabor
339202719Sgabor		putcharwrap(f, '.');
340202719Sgabor		num_base = new_number();
341202719Sgabor		bn_check(BN_set_word(num_base->number, base));
342202719Sgabor		BN_init(&mult);
343202719Sgabor		bn_check(BN_one(&mult));
344202719Sgabor		BN_init(&stop);
345202719Sgabor		bn_check(BN_one(&stop));
346202719Sgabor		scale_number(&stop, b->scale);
347202719Sgabor
348202719Sgabor		i = 0;
349202719Sgabor		while (BN_cmp(&mult, &stop) < 0) {
350203443Sgabor			u_long rem;
351202719Sgabor
352202719Sgabor			if (i && base > 16)
353202719Sgabor				putcharwrap(f, ' ');
354202719Sgabor			i = 1;
355202719Sgabor
356202719Sgabor			bmul_number(fract_part, fract_part, num_base);
357202719Sgabor			split_number(fract_part, int_part->number, NULL);
358202719Sgabor			rem = BN_get_word(int_part->number);
359202719Sgabor			p = get_digit(rem, digits, base);
360202719Sgabor			int_part->scale = 0;
361202719Sgabor			normalize(int_part, fract_part->scale);
362202719Sgabor			bn_check(BN_sub(fract_part->number, fract_part->number,
363202719Sgabor			    int_part->number));
364202719Sgabor			printwrap(f, p);
365202719Sgabor			free(p);
366202719Sgabor			bn_check(BN_mul_word(&mult, base));
367202719Sgabor		}
368202719Sgabor		free_number(num_base);
369202719Sgabor		BN_free(&mult);
370202719Sgabor		BN_free(&stop);
371202719Sgabor	}
372202719Sgabor	flushwrap(f);
373202719Sgabor	free_number(int_part);
374202719Sgabor	free_number(fract_part);
375202719Sgabor}
376202719Sgabor
377202719Sgaborvoid
378202719Sgaborprint_value(FILE *f, const struct value *value, const char *prefix, u_int base)
379202719Sgabor{
380202719Sgabor
381202719Sgabor	fputs(prefix, f);
382202719Sgabor	switch (value->type) {
383202719Sgabor	case BCODE_NONE:
384202719Sgabor		if (value->array != NULL)
385202719Sgabor			fputs("<array>", f);
386202719Sgabor		break;
387202719Sgabor	case BCODE_NUMBER:
388202719Sgabor		printnumber(f, value->u.num, base);
389202719Sgabor		break;
390202719Sgabor	case BCODE_STRING:
391202719Sgabor		fputs(value->u.string, f);
392202719Sgabor		break;
393202719Sgabor	}
394202719Sgabor}
395202719Sgabor
396202719Sgaborvoid
397202719Sgaborprint_ascii(FILE *f, const struct number *n)
398202719Sgabor{
399203443Sgabor	BIGNUM *v;
400203443Sgabor	int ch, i, numbits;
401202719Sgabor
402202719Sgabor	v = BN_dup(n->number);
403202719Sgabor	bn_checkp(v);
404202719Sgabor
405202719Sgabor	if (BN_cmp(v, &zero) < 0)
406202719Sgabor		bn_check(BN_sub(v, &zero, v));
407202719Sgabor
408202719Sgabor	numbits = BN_num_bytes(v) * 8;
409202719Sgabor	while (numbits > 0) {
410202719Sgabor		ch = 0;
411202719Sgabor		for (i = 0; i < 8; i++)
412202719Sgabor			ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i);
413202719Sgabor		putc(ch, f);
414202719Sgabor		numbits -= 8;
415202719Sgabor	}
416202719Sgabor	BN_free(v);
417202719Sgabor}
418