1From af96fb92052c307818eefa4b687f964f1e3f542e Mon Sep 17 00:00:00 2001 2From: Matt Weber <matthew.weber@rockwellcollins.com> 3Date: Thu, 12 Sep 2019 15:04:35 -0500 4Subject: [PATCH] notice read and write errors on input and output 5 6Quoting from the bug report: 7 bc (1.06-19ubuntu1) dapper; urgency=low 8 * Make dc notice read and write errors on its input and output. 9 I grepped for mentions of the strings `putc', `print', `getc', 10 `FILE', `stdin', `stdout' and `stderr' and added calls to new 11 error-checking functions unless it was clear from the 12 immediately-surrounding code that the program was exiting 13 nonzero, or would exit nonzero if the call failed. I ignored 14 hits in lib/getopt*, which seems to pervasively ignore write 15 errors when printing usage messages, in the hope that these 16 were correct. I _think_ I got them all. -iwj. 17 -- Ian Jackson <iwj@ubuntu.com> Tue, 4 Apr 2006 17:21:02 +0100 18 19Upsteam: 20https://sources.debian.org/patches/bc/1.07.1-2/05_notice_read_write_errors.diff/ 21 22[Reformatted to GIT for 1.0.7.1 by Matt W] 23Updated by Ryan Kavanagh <rak@debian.org> for 1.0.7.1 on 26 July 2017. 24Author: Ian Jackson <iwj@ubuntu.com> 25Origin: other 26Bug-Debian: http://bugs.debian.org/488735 27 28Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com> 29--- 30 bc/execute.c | 10 +++++++++- 31 bc/main.c | 3 +++ 32 bc/sbc.y | 2 ++ 33 bc/scan.c | 2 ++ 34 bc/scan.l | 3 +++ 35 bc/util.c | 15 ++++++++++++-- 36 dc/dc.c | 3 +++ 37 dc/eval.c | 55 +++++++++++++++++++++++++++++++++++++++------------- 38 dc/misc.c | 1 + 39 dc/numeric.c | 9 +++++++++ 40 dc/stack.c | 11 ++++++++++- 41 dc/string.c | 2 ++ 42 h/number.h | 11 +++++++---- 43 lib/number.c | 24 +++++++++++++++++++++++ 44 14 files changed, 129 insertions(+), 22 deletions(-) 45 46diff --git a/bc/execute.c b/bc/execute.c 47index 256e4b7..50eac49 100644 48--- a/bc/execute.c 49+++ b/bc/execute.c 50@@ -104,6 +104,7 @@ execute (void) 51 } 52 out_char ('\n'); 53 } 54+ checkferror_output(stdout); 55 } 56 #endif 57 58@@ -224,6 +225,7 @@ execute (void) 59 } 60 } 61 fflush (stdout); 62+ checkferror_output(stdout); 63 break; 64 65 case 'R' : /* Return from function */ 66@@ -259,6 +261,7 @@ execute (void) 67 if (inst == 'W') out_char ('\n'); 68 store_var (4); /* Special variable "last". */ 69 fflush (stdout); 70+ checkferror_output(stdout); 71 pop (); 72 break; 73 74@@ -342,6 +345,7 @@ execute (void) 75 case 'w' : /* Write a string to the output. */ 76 while ((ch = byte(&pc)) != '"') out_schar (ch); 77 fflush (stdout); 78+ checkferror_output(stdout); 79 break; 80 81 case 'x' : /* Exchange Top of Stack with the one under the tos. */ 82@@ -549,7 +553,10 @@ execute (void) 83 { 84 signal (SIGINT, use_quit); 85 if (had_sigint) 86- printf ("\ninterrupted execution.\n"); 87+ { 88+ printf ("\ninterrupted execution.\n"); 89+ checkferror_output(stdout); 90+ } 91 } 92 } 93 94@@ -584,6 +591,7 @@ input_char (void) 95 out_col = 0; /* Saw a new line */ 96 } 97 } 98+ checkferror_input(stdin); 99 100 /* Classify and preprocess the input character. */ 101 if (isdigit(in_ch)) 102diff --git a/bc/main.c b/bc/main.c 103index 012075c..c96207b 100644 104--- a/bc/main.c 105+++ b/bc/main.c 106@@ -353,6 +353,9 @@ use_quit (int sig) 107 errno = save; 108 #else 109 write (1, "\n(interrupt) Exiting bc.\n", 26); 110+#ifdef READLINE 111+ rl_initialize (); /* Clear readline buffer */ 112+#endif 113 bc_exit(0); 114 #endif 115 } 116diff --git a/bc/sbc.y b/bc/sbc.y 117index 586686b..921ab1e 100644 118--- a/bc/sbc.y 119+++ b/bc/sbc.y 120@@ -86,7 +86,9 @@ program : /* empty */ 121 if (interactive && !quiet) 122 { 123 show_bc_version (); 124+ checkferror_output(stdout); 125 welcome (); 126+ checkferror_output(stdout); 127 } 128 } 129 | program input_item 130diff --git a/bc/scan.c b/bc/scan.c 131index b237f55..8dee4e9 100644 132--- a/bc/scan.c 133+++ b/bc/scan.c 134@@ -791,6 +791,7 @@ bcel_input (char *buf, yy_size_t *result, int max) 135 if (bcel_len != 0) 136 history (hist, &histev, H_ENTER, bcel_line); 137 fflush (stdout); 138+ checkferror_output(stdout); 139 } 140 141 if (bcel_len <= max) 142@@ -863,6 +864,7 @@ rl_input (char *buf, int *result, int max) 143 add_history (rl_line); 144 rl_line[rl_len-1] = '\n'; 145 fflush (stdout); 146+ checkferror_output(stdout); 147 } 148 149 if (rl_len <= max) 150diff --git a/bc/scan.l b/bc/scan.l 151index eb2e2dd..79186bb 100644 152--- a/bc/scan.l 153+++ b/bc/scan.l 154@@ -99,6 +99,7 @@ bcel_input (char *buf, yy_size_t *result, int max) 155 if (bcel_len != 0) 156 history (hist, &histev, H_ENTER, bcel_line); 157 fflush (stdout); 158+ checkferror_output(stdout); 159 } 160 161 if (bcel_len <= max) 162@@ -171,6 +172,7 @@ rl_input (char *buf, int *result, int max) 163 add_history (rl_line); 164 rl_line[rl_len-1] = '\n'; 165 fflush (stdout); 166+ checkferror_output(stdout); 167 } 168 169 if (rl_len <= max) 170@@ -295,6 +297,7 @@ limits return(Limits); 171 if (c == EOF) 172 { 173 fprintf (stderr,"EOF encountered in a comment.\n"); 174+ checkferror_output(stderr); 175 break; 176 } 177 } 178diff --git a/bc/util.c b/bc/util.c 179index 8eba093..cacd796 100644 180--- a/bc/util.c 181+++ b/bc/util.c 182@@ -247,9 +247,10 @@ init_gen (void) 183 continue_label = 0; 184 next_label = 1; 185 out_count = 2; 186- if (compile_only) 187+ if (compile_only) { 188 printf ("@i"); 189- else 190+ checkferror_output(stdout); 191+ } else 192 init_load (); 193 had_error = FALSE; 194 did_gen = FALSE; 195@@ -272,6 +273,7 @@ generate (const char *str) 196 printf ("\n"); 197 out_count = 0; 198 } 199+ checkferror_output(stdout); 200 } 201 else 202 load_code (str); 203@@ -289,6 +291,7 @@ run_code(void) 204 if (compile_only) 205 { 206 printf ("@r\n"); 207+ checkferror_output(stdout); 208 out_count = 0; 209 } 210 else 211@@ -326,6 +329,7 @@ out_char (int ch) 212 } 213 putchar (ch); 214 } 215+ checkferror_output(stdout); 216 } 217 218 /* Output routines: Write a character CH to the standard output. 219@@ -355,6 +359,7 @@ out_schar (int ch) 220 } 221 putchar (ch); 222 } 223+ checkferror_output(stdout); 224 } 225 226 227@@ -639,6 +644,7 @@ limits(void) 228 #ifdef OLD_EQ_OP 229 printf ("Old assignment operatiors are valid. (=-, =+, ...)\n"); 230 #endif 231+ checkferror_output(stdout); 232 } 233 234 /* bc_malloc will check the return value so all other places do not 235@@ -703,6 +709,7 @@ yyerror (str, va_alist) 236 fprintf (stderr,"%s %d: ",name,line_no); 237 vfprintf (stderr, str, args); 238 fprintf (stderr, "\n"); 239+ checkferror_output(stderr); 240 had_error = TRUE; 241 va_end (args); 242 } 243@@ -743,6 +750,7 @@ ct_warn (mesg, va_alist) 244 fprintf (stderr,"%s %d: Error: ",name,line_no); 245 vfprintf (stderr, mesg, args); 246 fprintf (stderr, "\n"); 247+ checkferror_output(stderr); 248 had_error = TRUE; 249 } 250 else 251@@ -755,6 +763,7 @@ ct_warn (mesg, va_alist) 252 fprintf (stderr,"%s %d: (Warning) ",name,line_no); 253 vfprintf (stderr, mesg, args); 254 fprintf (stderr, "\n"); 255+ checkferror_output(stderr); 256 } 257 va_end (args); 258 } 259@@ -789,6 +798,7 @@ rt_error (mesg, va_alist) 260 va_end (args); 261 262 fprintf (stderr, "\n"); 263+ checkferror_output(stderr); 264 runtime_error = TRUE; 265 } 266 267@@ -823,6 +833,7 @@ rt_warn (const char *mesg) 268 va_end (args); 269 270 fprintf (stderr, "\n"); 271+ checkferror_output(stderr); 272 } 273 274 /* bc_exit: Make sure to reset the edit state. */ 275diff --git a/dc/dc.c b/dc/dc.c 276index 6a2bb26..ccdb1c2 100644 277--- a/dc/dc.c 278+++ b/dc/dc.c 279@@ -59,6 +59,7 @@ static void 280 bug_report_info DC_DECLVOID() 281 { 282 printf("Email bug reports to: bug-dc@gnu.org .\n"); 283+ checkferror_output(stdout); 284 } 285 286 static void 287@@ -69,6 +70,7 @@ show_version DC_DECLVOID() 288 This is free software; see the source for copying conditions. There is NO\n\ 289 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\ 290 to the extent permitted by law.\n", DC_COPYRIGHT); 291+ checkferror_output(stdout); 292 } 293 294 /* your generic usage function */ 295@@ -85,6 +87,7 @@ Usage: %s [OPTION] [file ...]\n\ 296 \n\ 297 ", progname); 298 bug_report_info(); 299+ checkferror_output(f); 300 } 301 302 /* returns a pointer to one past the last occurance of c in s, 303diff --git a/dc/eval.c b/dc/eval.c 304index 05a3d9e..6c54e61 100644 305--- a/dc/eval.c 306+++ b/dc/eval.c 307@@ -97,12 +97,15 @@ static int input_pushback; 308 static int 309 input_fil DC_DECLVOID() 310 { 311+ int c; 312 if (input_pushback != EOF){ 313- int c = input_pushback; 314+ c = input_pushback; 315 input_pushback = EOF; 316 return c; 317 } 318- return getc(input_fil_fp); 319+ c = getc(input_fil_fp); 320+ checkferror_input(input_fil_fp); 321+ return c; 322 } 323 324 /* passed as an argument to dc_getnum */ 325@@ -301,11 +304,13 @@ dc_func DC_DECLARG((c, peekc, negcmp)) 326 tmpint = dc_num2int(datum.v.number, DC_TOSS); 327 if (2 <= tmpint && tmpint <= DC_IBASE_MAX) 328 dc_ibase = tmpint; 329- else 330+ else { 331 fprintf(stderr, 332 "%s: input base must be a number \ 333 between 2 and %d (inclusive)\n", 334 progname, DC_IBASE_MAX); 335+ checkferror_output(stderr); 336+ } 337 } 338 break; 339 case 'k': /* set scale to value on top of stack */ 340@@ -313,11 +318,12 @@ between 2 and %d (inclusive)\n", 341 tmpint = -1; 342 if (datum.dc_type == DC_NUMBER) 343 tmpint = dc_num2int(datum.v.number, DC_TOSS); 344- if ( ! (tmpint >= 0) ) 345+ if ( ! (tmpint >= 0) ) { 346 fprintf(stderr, 347 "%s: scale must be a nonnegative number\n", 348 progname); 349- else 350+ checkferror_output(stderr); 351+ } else 352 dc_scale = tmpint; 353 } 354 break; 355@@ -341,11 +347,12 @@ between 2 and %d (inclusive)\n", 356 tmpint = 0; 357 if (datum.dc_type == DC_NUMBER) 358 tmpint = dc_num2int(datum.v.number, DC_TOSS); 359- if ( ! (tmpint > 1) ) 360+ if ( ! (tmpint > 1) ) { 361 fprintf(stderr, 362 "%s: output base must be a number greater than 1\n", 363 progname); 364- else 365+ checkferror_output(stderr); 366+ } else 367 dc_obase = tmpint; 368 } 369 break; 370@@ -378,6 +385,7 @@ between 2 and %d (inclusive)\n", 371 fprintf(stderr, 372 "%s: square root of nonnumeric attempted\n", 373 progname); 374+ checkferror_output(stderr); 375 }else if (dc_sqrt(datum.v.number, dc_scale, &tmpnum) == DC_SUCCESS){ 376 dc_free_num(&datum.v.number); 377 datum.v.number = tmpnum; 378@@ -424,6 +432,7 @@ between 2 and %d (inclusive)\n", 379 dc_garbage("at top of stack", -1); 380 } 381 fflush(stdout); 382+ checkferror_output(stdout); 383 break; 384 case 'Q': /* quit out of top-of-stack nested evals; 385 * pops value from stack; 386@@ -440,6 +449,7 @@ between 2 and %d (inclusive)\n", 387 fprintf(stderr, 388 "%s: Q command requires a number >= 1\n", 389 progname); 390+ checkferror_output(stderr); 391 } 392 break; 393 case 'R': /* pop a value off of the evaluation stack,; 394@@ -483,11 +493,12 @@ between 2 and %d (inclusive)\n", 395 if (datum.dc_type == DC_NUMBER) 396 tmpint = dc_num2int(datum.v.number, DC_TOSS); 397 if (dc_pop(&datum) == DC_SUCCESS){ 398- if (tmpint < 0) 399+ if (tmpint < 0) { 400 fprintf(stderr, 401 "%s: array index must be a nonnegative integer\n", 402 progname); 403- else 404+ checkferror_output(stderr); 405+ } else 406 dc_array_set(peekc, tmpint, datum); 407 } 408 } 409@@ -499,18 +510,21 @@ between 2 and %d (inclusive)\n", 410 tmpint = -1; 411 if (datum.dc_type == DC_NUMBER) 412 tmpint = dc_num2int(datum.v.number, DC_TOSS); 413- if (tmpint < 0) 414+ if (tmpint < 0) { 415 fprintf(stderr, 416 "%s: array index must be a nonnegative integer\n", 417 progname); 418- else 419+ checkferror_output(stderr); 420+ } else 421 dc_push(dc_array_get(peekc, tmpint)); 422 } 423 return DC_EATONE; 424 425 default: /* What did that user mean? */ 426 fprintf(stderr, "%s: ", progname); 427+ checkferror_output(stderr); 428 dc_show_id(stdout, c, " unimplemented\n"); 429+ checkferror_output(stdout); 430 break; 431 } 432 return DC_OKAY; 433@@ -538,6 +552,7 @@ evalstr DC_DECLARG((string)) 434 fprintf(stderr, 435 "%s: eval called with non-string argument\n", 436 progname); 437+ checkferror_output(stderr); 438 return DC_OKAY; 439 } 440 interrupt_seen = 0; 441@@ -635,6 +650,7 @@ evalstr DC_DECLARG((string)) 442 return DC_FAIL; 443 } 444 fprintf(stderr, "%s: unexpected EOS\n", progname); 445+ checkferror_output(stderr); 446 return DC_OKAY; 447 } 448 } 449@@ -692,6 +708,7 @@ dc_evalfile DC_DECLARG((fp)) 450 stdin_lookahead = EOF; 451 for (c=getc(fp); c!=EOF; c=peekc){ 452 peekc = getc(fp); 453+ checkferror_input(stdin); 454 /* 455 * The following if() is the only place where ``stdin_lookahead'' 456 * might be set to other than EOF: 457@@ -717,24 +734,30 @@ dc_evalfile DC_DECLARG((fp)) 458 signal(SIGINT, sigint_handler); 459 switch (dc_func(c, peekc, negcmp)){ 460 case DC_OKAY: 461- if (stdin_lookahead != peekc && fp == stdin) 462+ if (stdin_lookahead != peekc && fp == stdin) { 463 peekc = getc(fp); 464+ checkferror_input(stdin); 465+ } 466 break; 467 case DC_EATONE: 468 peekc = getc(fp); 469+ checkferror_input(fp); 470 break; 471 case DC_EVALREG: 472 /*commands which send us here shall guarantee that peekc!=EOF*/ 473 c = peekc; 474 peekc = getc(fp); 475+ checkferror_input(fp); 476 stdin_lookahead = peekc; 477 if (dc_register_get(c, &datum) != DC_SUCCESS) 478 break; 479 dc_push(datum); 480 /*@fallthrough@*/ 481 case DC_EVALTOS: 482- if (stdin_lookahead != peekc && fp == stdin) 483+ if (stdin_lookahead != peekc && fp == stdin) { 484 peekc = getc(fp); 485+ checkferror_input(stdin); 486+ } 487 if (dc_pop(&datum) == DC_SUCCESS){ 488 if (datum.dc_type == DC_NUMBER){ 489 dc_push(datum); 490@@ -744,6 +767,7 @@ dc_evalfile DC_DECLARG((fp)) 491 goto reset_and_exit_quit; 492 fprintf(stderr, "%s: Q command argument exceeded \ 493 string execution depth\n", progname); 494+ checkferror_output(stderr); 495 } 496 }else{ 497 dc_garbage("at top of stack", -1); 498@@ -756,8 +780,11 @@ string execution depth\n", progname); 499 fprintf(stderr, 500 "%s: Q command argument exceeded string execution depth\n", 501 progname); 502- if (stdin_lookahead != peekc && fp == stdin) 503+ checkferror_output(stderr); 504+ if (stdin_lookahead != peekc && fp == stdin) { 505 peekc = getc(fp); 506+ checkferror_input(stdin); 507+ } 508 break; 509 510 case DC_INT: 511diff --git a/dc/misc.c b/dc/misc.c 512index cd23602..cd910b8 100644 513--- a/dc/misc.c 514+++ b/dc/misc.c 515@@ -89,6 +89,7 @@ dc_show_id DC_DECLARG((fp, id, suffix)) 516 fprintf(fp, "'%c' (%#o)%s", (unsigned int) id, id, suffix); 517 else 518 fprintf(fp, "%#o%s", (unsigned int) id, suffix); 519+ checkferror_output(fp); 520 } 521 522 523diff --git a/dc/numeric.c b/dc/numeric.c 524index 37759de..60cfb85 100644 525--- a/dc/numeric.c 526+++ b/dc/numeric.c 527@@ -133,6 +133,7 @@ dc_div DC_DECLARG((a, b, kscale, result)) 528 bc_init_num(CastNumPtr(result)); 529 if (bc_divide(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){ 530 fprintf(stderr, "%s: divide by zero\n", progname); 531+ checkferror_output(stderr); 532 return DC_DOMAIN_ERROR; 533 } 534 return DC_SUCCESS; 535@@ -155,6 +156,7 @@ dc_divrem DC_DECLARG((a, b, kscale, quotient, remainder)) 536 if (bc_divmod(CastNum(a), CastNum(b), 537 CastNumPtr(quotient), CastNumPtr(remainder), kscale)){ 538 fprintf(stderr, "%s: divide by zero\n", progname); 539+ checkferror_output(stderr); 540 return DC_DOMAIN_ERROR; 541 } 542 return DC_SUCCESS; 543@@ -173,6 +175,7 @@ dc_rem DC_DECLARG((a, b, kscale, result)) 544 bc_init_num(CastNumPtr(result)); 545 if (bc_modulo(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){ 546 fprintf(stderr, "%s: remainder by zero\n", progname); 547+ checkferror_output(stderr); 548 return DC_DOMAIN_ERROR; 549 } 550 return DC_SUCCESS; 551@@ -225,6 +228,7 @@ dc_sqrt DC_DECLARG((value, kscale, result)) 552 tmp = bc_copy_num(CastNum(value)); 553 if (!bc_sqrt(&tmp, kscale)){ 554 fprintf(stderr, "%s: square root of negative number\n", progname); 555+ checkferror_output(stderr); 556 bc_free_num(&tmp); 557 return DC_DOMAIN_ERROR; 558 } 559@@ -470,6 +474,7 @@ dc_dump_num DC_DECLARG((dcvalue, discard_p)) 560 561 for (cur=top_of_stack; cur; cur=next) { 562 putchar(cur->digit); 563+ checkferror_output(stdout); 564 next = cur->link; 565 free(cur); 566 } 567@@ -587,6 +592,8 @@ out_char (ch) 568 out_col = 1; 569 } 570 putchar(ch); 571+ checkferror_output(stdout); 572+ checkferror_output(stderr); 573 } 574 } 575 576@@ -626,6 +633,7 @@ rt_error (mesg, va_alist) 577 vfprintf (stderr, mesg, args); 578 va_end (args); 579 fprintf (stderr, "\n"); 580+ checkferror_output(stderr); 581 } 582 583 584@@ -659,6 +667,7 @@ rt_warn (mesg, va_alist) 585 vfprintf (stderr, mesg, args); 586 va_end (args); 587 fprintf (stderr, "\n"); 588+ checkferror_output(stderr); 589 } 590 591 592diff --git a/dc/stack.c b/dc/stack.c 593index 49422df..174411d 100644 594--- a/dc/stack.c 595+++ b/dc/stack.c 596@@ -35,7 +35,10 @@ 597 #include "dc-regdef.h" 598 599 /* an oft-used error message: */ 600-#define Empty_Stack fprintf(stderr, "%s: stack empty\n", progname) 601+#define Empty_Stack do{ \ 602+ fprintf(stderr, "%s: stack empty\n", progname); \ 603+ checkferror_output(stderr); \ 604+ }while(0) 605 606 607 /* simple linked-list implementation suffices: */ 608@@ -91,6 +94,7 @@ dc_binop DC_DECLARG((op, kscale)) 609 if (dc_stack->value.dc_type!=DC_NUMBER 610 || dc_stack->link->value.dc_type!=DC_NUMBER){ 611 fprintf(stderr, "%s: non-numeric value\n", progname); 612+ checkferror_output(stderr); 613 return; 614 } 615 (void)dc_pop(&b); 616@@ -131,6 +135,7 @@ dc_binop2 DC_DECLARG((op, kscale)) 617 if (dc_stack->value.dc_type!=DC_NUMBER 618 || dc_stack->link->value.dc_type!=DC_NUMBER){ 619 fprintf(stderr, "%s: non-numeric value\n", progname); 620+ checkferror_output(stderr); 621 return; 622 } 623 (void)dc_pop(&b); 624@@ -169,6 +174,7 @@ dc_cmpop DC_DECLVOID() 625 if (dc_stack->value.dc_type!=DC_NUMBER 626 || dc_stack->link->value.dc_type!=DC_NUMBER){ 627 fprintf(stderr, "%s: non-numeric value\n", progname); 628+ checkferror_output(stderr); 629 return 0; 630 } 631 (void)dc_pop(&b); 632@@ -206,6 +212,7 @@ dc_triop DC_DECLARG((op, kscale)) 633 || dc_stack->link->value.dc_type!=DC_NUMBER 634 || dc_stack->link->link->value.dc_type!=DC_NUMBER){ 635 fprintf(stderr, "%s: non-numeric value\n", progname); 636+ checkferror_output(stderr); 637 return; 638 } 639 (void)dc_pop(&c); 640@@ -327,6 +334,7 @@ dc_register_get DC_DECLARG((regid, result)) 641 *result = dc_int2data(0); 642 }else if (r->value.dc_type==DC_UNINITIALIZED){ 643 fprintf(stderr, "%s: BUG: register ", progname); 644+ checkferror_output(stderr); 645 dc_show_id(stderr, regid, " exists but is uninitialized?\n"); 646 return DC_FAIL; 647 }else{ 648@@ -402,6 +410,7 @@ dc_register_pop DC_DECLARG((stackid, result)) 649 r = dc_register[stackid]; 650 if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){ 651 fprintf(stderr, "%s: stack register ", progname); 652+ checkferror_output(stderr); 653 dc_show_id(stderr, stackid, " is empty\n"); 654 return DC_FAIL; 655 } 656diff --git a/dc/string.c b/dc/string.c 657index dee9169..389d899 100644 658--- a/dc/string.c 659+++ b/dc/string.c 660@@ -94,6 +94,7 @@ dc_out_str DC_DECLARG((value, discard_flag)) 661 dc_discard discard_flag DC_DECLEND 662 { 663 fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout); 664+ checkferror_output(stdout); 665 if (discard_flag == DC_TOSS) 666 dc_free_str(&value); 667 } 668@@ -169,6 +170,7 @@ dc_readstring DC_DECLARG((fp, ldelim, rdelim)) 669 } 670 *p++ = c; 671 } 672+ checkferror_input(fp); 673 return dc_makestring(line_buf, (size_t)(p-line_buf)); 674 } 675 676diff --git a/h/number.h b/h/number.h 677index abf6332..1983ab4 100644 678--- a/h/number.h 679+++ b/h/number.h 680@@ -23,10 +23,10 @@ 681 You may contact the author by: 682 e-mail: philnelson@acm.org 683 us-mail: Philip A. Nelson 684- Computer Science Department, 9062 685- Western Washington University 686- Bellingham, WA 98226-9062 687- 688+ Computer Science Department, 9062 689+ Western Washington University 690+ Bellingham, WA 98226-9062 691+ 692 *************************************************************************/ 693 694 #ifndef _NUMBER_H_ 695@@ -140,4 +140,7 @@ void bc_out_num (bc_num num, int o_base, void (* out_char)(int), 696 int leading_zero); 697 698 void bc_out_long (long val, int size, int space, void (*out_char)(int)); 699+ 700+void checkferror_input (FILE*); 701+void checkferror_output (FILE*); 702 #endif 703diff --git a/lib/number.c b/lib/number.c 704index f394e92..80b33e3 100644 705--- a/lib/number.c 706+++ b/lib/number.c 707@@ -1713,6 +1713,7 @@ static void 708 out_char (int c) 709 { 710 putchar(c); 711+ checkferror_output(stdout); 712 } 713 714 715@@ -1721,6 +1722,7 @@ pn (bc_num num) 716 { 717 bc_out_num (num, 10, out_char, 0); 718 out_char ('\n'); 719+ checkferror_output(stdout); 720 } 721 722 723@@ -1732,6 +1734,28 @@ pv (char *name, unsigned char *num, int len) 724 printf ("%s=", name); 725 for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i])); 726 printf ("\n"); 727+ checkferror_output(stdout); 728 } 729 730 #endif 731+ 732+/* check ferror() status and if so die */ 733+void 734+checkferror_input (fp) 735+ FILE *fp; 736+{ 737+ if (ferror(fp)) { 738+ perror("dc: could not read input file"); 739+ exit(EXIT_FAILURE); 740+ } 741+} 742+ 743+void 744+checkferror_output (fp) 745+ FILE *fp; 746+{ 747+ if (ferror(fp)) { 748+ perror("dc: could not write output file"); 749+ exit(EXIT_FAILURE); 750+ } 751+} 752-- 7532.17.1 754 755