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