1 /* $OpenBSD: inout.c,v 1.18 2014/12/01 13:13:00 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/cdefs.h> 20 __FBSDID("$FreeBSD$"); 21 22 #include <openssl/ssl.h> 23 #include <ctype.h> 24 #include <err.h> 25 #include <string.h> 26 27 #include "extern.h" 28 29 #define MAX_CHARS_PER_LINE 68 30 31 static int lastchar; 32 static int charcount; 33 34 static int src_getcharstream(struct source *); 35 static void src_ungetcharstream(struct source *); 36 static char *src_getlinestream(struct source *); 37 static int src_getcharstring(struct source *); 38 static void src_ungetcharstring(struct source *); 39 static char *src_getlinestring(struct source *); 40 static void src_freestring(struct source *); 41 static void flushwrap(FILE *); 42 static void putcharwrap(FILE *, int); 43 static void printwrap(FILE *, const char *); 44 static char *get_digit(u_long, int, u_int); 45 46 static struct vtable stream_vtable = { 47 src_getcharstream, 48 src_ungetcharstream, 49 src_getlinestream, 50 NULL 51 }; 52 53 static struct vtable string_vtable = { 54 src_getcharstring, 55 src_ungetcharstring, 56 src_getlinestring, 57 src_freestring 58 }; 59 60 void 61 src_setstream(struct source *src, FILE *stream) 62 { 63 64 src->u.stream = stream; 65 src->vtable = &stream_vtable; 66 } 67 68 void 69 src_setstring(struct source *src, char *p) 70 { 71 72 src->u.string.buf = (u_char *)p; 73 src->u.string.pos = 0; 74 src->vtable = &string_vtable; 75 } 76 77 static int 78 src_getcharstream(struct source *src) 79 { 80 81 return (src->lastchar = getc(src->u.stream)); 82 } 83 84 static void 85 src_ungetcharstream(struct source *src) 86 { 87 88 ungetc(src->lastchar, src->u.stream); 89 } 90 91 static char * 92 src_getlinestream(struct source *src) 93 { 94 char buf[BUFSIZ]; 95 96 if (fgets(buf, BUFSIZ, src->u.stream) == NULL) 97 return (bstrdup("")); 98 return bstrdup(buf); 99 } 100 101 static int 102 src_getcharstring(struct source *src) 103 { 104 105 src->lastchar = src->u.string.buf[src->u.string.pos]; 106 if (src->lastchar == '\0') 107 return (EOF); 108 else { 109 src->u.string.pos++; 110 return (src->lastchar); 111 } 112 } 113 114 static void 115 src_ungetcharstring(struct source *src) 116 { 117 118 if (src->u.string.pos > 0) { 119 if (src->lastchar != '\0') 120 --src->u.string.pos; 121 } 122 } 123 124 static char * 125 src_getlinestring(struct source *src) 126 { 127 char buf[BUFSIZ]; 128 int i, ch; 129 130 i = 0; 131 while (i < BUFSIZ-1) { 132 ch = src_getcharstring(src); 133 if (ch == EOF) 134 break; 135 buf[i++] = ch; 136 if (ch == '\n') 137 break; 138 } 139 buf[i] = '\0'; 140 return (bstrdup(buf)); 141 } 142 143 static void 144 src_freestring(struct source *src) 145 { 146 147 free(src->u.string.buf); 148 } 149 150 static void 151 flushwrap(FILE *f) 152 { 153 154 if (lastchar != -1) 155 putc(lastchar, f); 156 } 157 158 static void 159 putcharwrap(FILE *f, int ch) 160 { 161 162 if (charcount >= MAX_CHARS_PER_LINE) { 163 charcount = 0; 164 fputs("\\\n", f); 165 } 166 if (lastchar != -1) { 167 charcount++; 168 putc(lastchar, f); 169 } 170 lastchar = ch; 171 } 172 173 static void 174 printwrap(FILE *f, const char *p) 175 { 176 char *q; 177 char buf[12]; 178 179 q = buf; 180 strlcpy(buf, p, sizeof(buf)); 181 while (*q) 182 putcharwrap(f, *q++); 183 } 184 185 struct number * 186 readnumber(struct source *src, u_int base, u_int bscale) 187 { 188 struct number *n; 189 BN_ULONG v; 190 int ch; 191 u_int iscale = 0; 192 bool dot = false, sign = false; 193 194 n = new_number(); 195 bn_check(BN_zero(n->number)); 196 197 while ((ch = (*src->vtable->readchar)(src)) != EOF) { 198 199 if ('0' <= ch && ch <= '9') 200 v = ch - '0'; 201 else if ('A' <= ch && ch <= 'F') 202 v = ch - 'A' + 10; 203 else if (ch == '_') { 204 sign = true; 205 continue; 206 } else if (ch == '.') { 207 if (dot) 208 break; 209 dot = true; 210 continue; 211 } else { 212 (*src->vtable->unreadchar)(src); 213 break; 214 } 215 if (dot) 216 iscale++; 217 218 bn_check(BN_mul_word(n->number, base)); 219 bn_check(BN_add_word(n->number, v)); 220 } 221 if (base == 10) { 222 n->scale = iscale; 223 } else { 224 /* At this point, the desired result is n->number / base^iscale*/ 225 struct number *quotient, *divisor, *_n; 226 BIGNUM *base_n, *exponent; 227 BN_CTX *ctx; 228 229 ctx = BN_CTX_new(); 230 base_n = BN_new(); 231 exponent = BN_new(); 232 divisor = new_number(); 233 bn_check(BN_zero(base_n)); 234 bn_check(BN_zero(exponent)); 235 236 bn_check(BN_add_word(base_n, base)); 237 bn_check(BN_add_word(exponent, iscale)); 238 bn_check(BN_exp(divisor->number, base_n, exponent, ctx)); 239 divisor->scale = 0; 240 quotient = div_number(n, divisor, bscale); 241 _n = n; 242 n = quotient; 243 244 /* 245 * Trim off trailing zeros to yield the smallest scale without 246 * loss of accuracy 247 */ 248 while ( n->scale > 0 && 249 BN_mod_word(n->number, 10) == 0) { 250 normalize(n, n->scale - 1); 251 } 252 253 free_number(_n); 254 free_number(divisor); 255 BN_CTX_free(ctx); 256 BN_free(base_n); 257 BN_free(exponent); 258 } 259 if (sign) 260 negate(n); 261 return (n); 262 } 263 264 char * 265 read_string(struct source *src) 266 { 267 char *p; 268 int count, ch, i, new_sz, sz; 269 bool escape; 270 271 escape = false; 272 count = 1; 273 i = 0; 274 sz = 15; 275 p = bmalloc(sz + 1); 276 277 while ((ch = (*src->vtable->readchar)(src)) != EOF) { 278 if (!escape) { 279 if (ch == '[') 280 count++; 281 else if (ch == ']') 282 count--; 283 if (count == 0) 284 break; 285 } 286 if (ch == '\\' && !escape) 287 escape = true; 288 else { 289 escape = false; 290 if (i == sz) { 291 new_sz = sz * 2; 292 p = breallocarray(p, 1, new_sz + 1); 293 sz = new_sz; 294 } 295 p[i++] = ch; 296 } 297 } 298 p[i] = '\0'; 299 return (p); 300 } 301 302 static char * 303 get_digit(u_long num, int digits, u_int base) 304 { 305 char *p; 306 307 if (base <= 16) { 308 p = bmalloc(2); 309 p[0] = num >= 10 ? num + 'A' - 10 : num + '0'; 310 p[1] = '\0'; 311 } else { 312 if (asprintf(&p, "%0*lu", digits, num) == -1) 313 err(1, NULL); 314 } 315 return (p); 316 } 317 318 void 319 printnumber(FILE *f, const struct number *b, u_int base) 320 { 321 struct number *fract_part, *int_part; 322 struct stack stack; 323 char *p; 324 char buf[11]; 325 size_t sz; 326 unsigned int i; 327 int digits; 328 329 charcount = 0; 330 lastchar = -1; 331 if (BN_is_zero(b->number)) 332 putcharwrap(f, '0'); 333 334 int_part = new_number(); 335 fract_part = new_number(); 336 fract_part->scale = b->scale; 337 338 if (base <= 16) 339 digits = 1; 340 else { 341 digits = snprintf(buf, sizeof(buf), "%u", base-1); 342 } 343 split_number(b, int_part->number, fract_part->number); 344 345 i = 0; 346 stack_init(&stack); 347 while (!BN_is_zero(int_part->number)) { 348 BN_ULONG rem = BN_div_word(int_part->number, base); 349 stack_pushstring(&stack, get_digit(rem, digits, base)); 350 i++; 351 } 352 sz = i; 353 if (BN_is_negative(b->number)) 354 putcharwrap(f, '-'); 355 for (i = 0; i < sz; i++) { 356 p = stack_popstring(&stack); 357 if (base > 16) 358 putcharwrap(f, ' '); 359 printwrap(f, p); 360 free(p); 361 } 362 stack_clear(&stack); 363 if (b->scale > 0) { 364 struct number *num_base; 365 BIGNUM *mult, *stop; 366 367 putcharwrap(f, '.'); 368 num_base = new_number(); 369 bn_check(BN_set_word(num_base->number, base)); 370 mult = BN_new(); 371 bn_checkp(mult); 372 bn_check(BN_one(mult)); 373 stop = BN_new(); 374 bn_checkp(stop); 375 bn_check(BN_one(stop)); 376 scale_number(stop, b->scale); 377 378 i = 0; 379 while (BN_cmp(mult, stop) < 0) { 380 u_long rem; 381 382 if (i && base > 16) 383 putcharwrap(f, ' '); 384 i = 1; 385 386 bmul_number(fract_part, fract_part, num_base, 387 bmachine_scale()); 388 split_number(fract_part, int_part->number, NULL); 389 rem = BN_get_word(int_part->number); 390 p = get_digit(rem, digits, base); 391 int_part->scale = 0; 392 normalize(int_part, fract_part->scale); 393 bn_check(BN_sub(fract_part->number, fract_part->number, 394 int_part->number)); 395 printwrap(f, p); 396 free(p); 397 bn_check(BN_mul_word(mult, base)); 398 } 399 free_number(num_base); 400 BN_free(mult); 401 BN_free(stop); 402 } 403 flushwrap(f); 404 free_number(int_part); 405 free_number(fract_part); 406 } 407 408 void 409 print_value(FILE *f, const struct value *value, const char *prefix, u_int base) 410 { 411 412 fputs(prefix, f); 413 switch (value->type) { 414 case BCODE_NONE: 415 if (value->array != NULL) 416 fputs("<array>", f); 417 break; 418 case BCODE_NUMBER: 419 printnumber(f, value->u.num, base); 420 break; 421 case BCODE_STRING: 422 fputs(value->u.string, f); 423 break; 424 } 425 } 426 427 void 428 print_ascii(FILE *f, const struct number *n) 429 { 430 BIGNUM *v; 431 int ch, i, numbits; 432 433 v = BN_dup(n->number); 434 bn_checkp(v); 435 436 if (BN_is_negative(v)) 437 BN_set_negative(v, 0); 438 439 numbits = BN_num_bytes(v) * 8; 440 while (numbits > 0) { 441 ch = 0; 442 for (i = 0; i < 8; i++) 443 ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i); 444 putc(ch, f); 445 numbits -= 8; 446 } 447 BN_free(v); 448 } 449