1 Description: notice read and write errors on input and output
2 Quoting from the bug report:
3 +bc (1.06-19ubuntu1) dapper; urgency=low
5 + * Make dc notice read and write errors on its input and output.
6 + I grepped for mentions of the strings `putc', `print', `getc', `FILE',
7 + `stdin', `stdout' and `stderr' and added calls to new error-checking
8 + functions unless it was clear from the immediately-surrounding code
9 + that the program was exiting nonzero, or would exit nonzero if the
10 + call failed. I ignored hits in lib/getopt*, which seems to
11 + pervasively ignore write errors when printing usage messages, in the
12 + hope that these were correct. I _think_ I got them all. -iwj.
14 + -- Ian Jackson <iwj@ubuntu.com> Tue, 4 Apr 2006 17:21:02 +0100
15 Author: Ian Jackson <iwj@ubuntu.com>
17 Bug-Debian: http://bugs.debian.org/488735
19 This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
20 diff --git a/bc/execute.c b/bc/execute.c
21 index e4e8ef7..8787048 100644
24 @@ -108,6 +108,7 @@ execute ()
28 + checkferror_output(stdout);
32 @@ -222,6 +223,7 @@ execute ()
36 + checkferror_output(stdout);
39 case 'R' : /* Return from function */
40 @@ -257,6 +259,7 @@ execute ()
41 if (inst == 'W') out_char ('\n');
42 store_var (4); /* Special variable "last". */
44 + checkferror_output(stdout);
48 @@ -338,6 +341,7 @@ execute ()
49 case 'w' : /* Write a string to the output. */
50 while ((ch = byte(&pc)) != '"') out_schar (ch);
52 + checkferror_output(stdout);
55 case 'x' : /* Exchange Top of Stack with the one under the tos. */
56 @@ -545,7 +549,10 @@ execute ()
58 signal (SIGINT, use_quit);
60 - printf ("\ninterrupted execution.\n");
62 + printf ("\ninterrupted execution.\n");
63 + checkferror_output(stdout);
68 @@ -580,6 +587,7 @@ input_char ()
69 out_col = 0; /* Saw a new line */
72 + checkferror_input(stdin);
74 /* Classify and preprocess the input character. */
76 diff --git a/bc/load.c b/bc/load.c
77 index 1035198..4039e86 100644
80 @@ -217,6 +217,7 @@ load_code (code)
81 if (label_no > 65535L)
82 { /* Better message? */
83 fprintf (stderr,"Program too big.\n");
84 + checkferror_output(stderr);
87 addbyte ( (char) (label_no & 0xFF));
88 diff --git a/bc/main.c b/bc/main.c
89 index 9a2461e..3ae427d 100644
92 @@ -358,6 +358,9 @@ use_quit (sig)
95 write (1, "\n(interrupt) Exiting bc.\n", 26);
97 + rl_initialize (); /* Clear readline buffer */
102 diff --git a/bc/sbc.y b/bc/sbc.y
103 index 0ded29e..6fcc1fa 100644
106 @@ -86,7 +86,9 @@ program : /* empty */
107 if (interactive && !quiet)
110 + checkferror_output(stdout);
112 + checkferror_output(stdout);
116 diff --git a/bc/scan.c b/bc/scan.c
117 index 1f78ec2..2b5eeb4 100644
120 @@ -799,6 +799,7 @@ bcel_input (buf, result, max)
122 history (hist, &histev, H_ENTER, bcel_line);
124 + checkferror_output(stdout);
128 @@ -874,6 +875,7 @@ rl_input (buf, result, max)
129 add_history (rl_line);
130 rl_line[rl_len-1] = '\n';
132 + checkferror_output(stdout);
136 diff --git a/bc/scan.l b/bc/scan.l
137 index 841c3df..16cd62e 100644
140 @@ -111,6 +111,7 @@ bcel_input (buf, result, max)
142 history (hist, &histev, H_ENTER, bcel_line);
144 + checkferror_output(stdout);
148 @@ -186,6 +187,7 @@ rl_input (buf, result, max)
149 add_history (rl_line);
150 rl_line[rl_len-1] = '\n';
152 + checkferror_output(stdout);
156 @@ -310,6 +312,7 @@ limits return(Limits);
159 fprintf (stderr,"EOF encountered in a comment.\n");
160 + checkferror_output(stderr);
164 diff --git a/bc/storage.c b/bc/storage.c
165 index 699729a..37b4c6c 100644
168 @@ -99,6 +99,7 @@ more_functions (VOID)
170 f = &functions[indx];
171 f->f_defined = FALSE;
173 f->f_body = (char *) bc_malloc (BC_START_SIZE);
174 f->f_body_size = BC_START_SIZE;
176 diff --git a/bc/util.c b/bc/util.c
177 index 30beaf9..669235f 100644
180 @@ -260,9 +260,10 @@ init_gen ()
185 + if (compile_only) {
188 + checkferror_output(stdout);
193 @@ -286,6 +287,7 @@ generate (str)
197 + checkferror_output(stdout);
201 @@ -303,6 +305,7 @@ run_code()
205 + checkferror_output(stdout);
209 @@ -341,6 +344,7 @@ out_char (ch)
213 + checkferror_output(stdout);
216 /* Output routines: Write a character CH to the standard output.
217 @@ -371,6 +375,7 @@ out_schar (ch)
221 + checkferror_output(stdout);
225 @@ -657,6 +662,7 @@ limits()
227 printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
229 + checkferror_output(stdout);
232 /* bc_malloc will check the return value so all other places do not
233 @@ -721,6 +727,7 @@ yyerror (str, va_alist)
234 fprintf (stderr,"%s %d: ",name,line_no);
235 vfprintf (stderr, str, args);
236 fprintf (stderr, "\n");
237 + checkferror_output(stderr);
241 @@ -761,6 +768,7 @@ warn (mesg, va_alist)
242 fprintf (stderr,"%s %d: Error: ",name,line_no);
243 vfprintf (stderr, mesg, args);
244 fprintf (stderr, "\n");
245 + checkferror_output(stderr);
249 @@ -773,6 +781,7 @@ warn (mesg, va_alist)
250 fprintf (stderr,"%s %d: (Warning) ",name,line_no);
251 vfprintf (stderr, mesg, args);
252 fprintf (stderr, "\n");
253 + checkferror_output(stderr);
257 @@ -807,6 +816,7 @@ rt_error (mesg, va_alist)
260 fprintf (stderr, "\n");
261 + checkferror_output(stderr);
262 runtime_error = TRUE;
265 @@ -843,4 +853,5 @@ rt_warn (mesg, va_alist)
268 fprintf (stderr, "\n");
269 + checkferror_output(stderr);
271 diff --git a/dc/dc.c b/dc/dc.c
272 index e03f094..0faf03a 100644
275 @@ -61,6 +61,7 @@ static void
276 bug_report_info DC_DECLVOID()
278 printf("Email bug reports to: bug-dc@gnu.org .\n");
279 + checkferror_output(stdout);
283 @@ -71,6 +72,7 @@ show_version DC_DECLVOID()
284 This is free software; see the source for copying conditions. There is NO\n\
285 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
286 to the extent permitted by law.\n", DC_COPYRIGHT);
287 + checkferror_output(stdout);
290 /* your generic usage function */
291 @@ -87,6 +89,7 @@ Usage: %s [OPTION] [file ...]\n\
295 + checkferror_output(f);
298 /* returns a pointer to one past the last occurance of c in s,
299 diff --git a/dc/eval.c b/dc/eval.c
300 index 4af7200..153d331 100644
303 @@ -94,12 +94,15 @@ static int input_pushback;
305 input_fil DC_DECLVOID()
308 if (input_pushback != EOF){
309 - int c = input_pushback;
310 + c = input_pushback;
311 input_pushback = EOF;
314 - return getc(input_fil_fp);
315 + c = getc(input_fil_fp);
316 + checkferror_input(input_fil_fp);
320 /* passed as an argument to dc_getnum */
321 @@ -298,11 +301,13 @@ dc_func DC_DECLARG((c, peekc, negcmp))
322 tmpint = dc_num2int(datum.v.number, DC_TOSS);
323 if (2 <= tmpint && tmpint <= DC_IBASE_MAX)
328 "%s: input base must be a number \
329 between 2 and %d (inclusive)\n",
330 progname, DC_IBASE_MAX);
331 + checkferror_output(stderr);
335 case 'k': /* set scale to value on top of stack */
336 @@ -310,11 +315,12 @@ between 2 and %d (inclusive)\n",
338 if (datum.dc_type == DC_NUMBER)
339 tmpint = dc_num2int(datum.v.number, DC_TOSS);
340 - if ( ! (tmpint >= 0) )
341 + if ( ! (tmpint >= 0) ) {
343 "%s: scale must be a nonnegative number\n",
346 + checkferror_output(stderr);
351 @@ -338,11 +344,12 @@ between 2 and %d (inclusive)\n",
353 if (datum.dc_type == DC_NUMBER)
354 tmpint = dc_num2int(datum.v.number, DC_TOSS);
355 - if ( ! (tmpint > 1) )
356 + if ( ! (tmpint > 1) ) {
358 "%s: output base must be a number greater than 1\n",
361 + checkferror_output(stderr);
366 @@ -383,6 +390,7 @@ between 2 and %d (inclusive)\n",
368 "%s: square root of nonnumeric attempted\n",
370 + checkferror_output(stderr);
371 }else if (dc_sqrt(datum.v.number, dc_scale, &tmpnum) == DC_SUCCESS){
372 dc_free_num(&datum.v.number);
373 datum.v.number = tmpnum;
374 @@ -444,6 +452,7 @@ between 2 and %d (inclusive)\n",
376 "%s: Q command requires a number >= 1\n",
378 + checkferror_output(stderr);
382 @@ -489,11 +498,12 @@ between 2 and %d (inclusive)\n",
383 if (datum.dc_type == DC_NUMBER)
384 tmpint = dc_num2int(datum.v.number, DC_TOSS);
385 if (dc_pop(&datum) == DC_SUCCESS){
389 "%s: array index must be a nonnegative integer\n",
392 + checkferror_output(stderr);
394 dc_array_set(peekc, tmpint, datum);
397 @@ -505,17 +515,19 @@ between 2 and %d (inclusive)\n",
399 if (datum.dc_type == DC_NUMBER)
400 tmpint = dc_num2int(datum.v.number, DC_TOSS);
404 "%s: array index must be a nonnegative integer\n",
407 + checkferror_output(stderr);
409 dc_push(dc_array_get(peekc, tmpint));
413 default: /* What did that user mean? */
414 fprintf(stderr, "%s: ", progname);
415 + checkferror_output(stderr);
416 dc_show_id(stdout, c, " unimplemented\n");
419 @@ -544,6 +556,7 @@ dc_evalstr DC_DECLARG((string))
421 "%s: eval called with non-string argument\n",
423 + checkferror_output(stderr);
427 @@ -640,6 +653,7 @@ dc_evalstr DC_DECLARG((string))
430 fprintf(stderr, "%s: unexpected EOS\n", progname);
431 + checkferror_output(stderr);
435 @@ -665,6 +679,7 @@ dc_evalfile DC_DECLARG((fp))
436 stdin_lookahead = EOF;
437 for (c=getc(fp); c!=EOF; c=peekc){
439 + checkferror_input(stdin);
441 * The following if() is the only place where ``stdin_lookahead''
442 * might be set to other than EOF:
443 @@ -716,6 +731,7 @@ dc_evalfile DC_DECLARG((fp))
445 fprintf(stderr, "%s: Q command argument exceeded \
446 string execution depth\n", progname);
447 + checkferror_output(stderr);
450 dc_garbage("at top of stack", -1);
451 @@ -728,8 +744,11 @@ string execution depth\n", progname);
453 "%s: Q command argument exceeded string execution depth\n",
455 - if (stdin_lookahead != peekc && fp == stdin)
456 + checkferror_output(stderr);
457 + if (stdin_lookahead != peekc && fp == stdin) {
459 + checkferror_input(stdin);
464 @@ -771,6 +790,7 @@ string execution depth\n", progname);
467 fprintf(stderr, "%s: unexpected EOF\n", progname);
468 + checkferror_output(stderr);
472 diff --git a/dc/misc.c b/dc/misc.c
473 index f2388b0..1be56fe 100644
476 @@ -91,6 +91,7 @@ dc_show_id DC_DECLARG((fp, id, suffix))
477 fprintf(fp, "'%c' (%#o)%s", (unsigned int) id, id, suffix);
479 fprintf(fp, "%#o%s", (unsigned int) id, suffix);
480 + checkferror_output(fp);
484 diff --git a/dc/numeric.c b/dc/numeric.c
485 index 8e5e70f..c875eba 100644
488 @@ -134,6 +134,7 @@ dc_div DC_DECLARG((a, b, kscale, result))
489 bc_init_num(CastNumPtr(result));
490 if (bc_divide(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){
491 fprintf(stderr, "%s: divide by zero\n", progname);
492 + checkferror_output(stderr);
493 return DC_DOMAIN_ERROR;
496 @@ -156,6 +157,7 @@ dc_divrem DC_DECLARG((a, b, kscale, quotient, remainder))
497 if (bc_divmod(CastNum(a), CastNum(b),
498 CastNumPtr(quotient), CastNumPtr(remainder), kscale)){
499 fprintf(stderr, "%s: divide by zero\n", progname);
500 + checkferror_output(stderr);
501 return DC_DOMAIN_ERROR;
504 @@ -174,6 +176,7 @@ dc_rem DC_DECLARG((a, b, kscale, result))
505 bc_init_num(CastNumPtr(result));
506 if (bc_modulo(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){
507 fprintf(stderr, "%s: remainder by zero\n", progname);
508 + checkferror_output(stderr);
509 return DC_DOMAIN_ERROR;
512 @@ -226,6 +229,7 @@ dc_sqrt DC_DECLARG((value, kscale, result))
513 tmp = bc_copy_num(CastNum(value));
514 if (!bc_sqrt(&tmp, kscale)){
515 fprintf(stderr, "%s: square root of negative number\n", progname);
516 + checkferror_output(stderr);
518 return DC_DOMAIN_ERROR;
520 @@ -429,8 +433,10 @@ dc_out_num DC_DECLARG((value, obase, newline_p, discard_p))
522 out_char('\0'); /* clear the column counter */
523 bc_out_num(CastNum(value), obase, out_char, 0);
524 - if (newline_p == DC_WITHNL)
525 + if (newline_p == DC_WITHNL) {
527 + checkferror_output(stdout);
529 if (discard_p == DC_TOSS)
532 @@ -475,6 +481,7 @@ dc_dump_num DC_DECLARG((dcvalue, discard_p))
534 for (cur=top_of_stack; cur; cur=next) {
536 + checkferror_output(stdout);
540 @@ -592,6 +599,7 @@ out_char (ch)
544 + checkferror_output(stderr);
548 @@ -631,6 +639,7 @@ rt_error (mesg, va_alist)
549 vfprintf (stderr, mesg, args);
551 fprintf (stderr, "\n");
552 + checkferror_output(stderr);
556 @@ -664,6 +673,7 @@ rt_warn (mesg, va_alist)
557 vfprintf (stderr, mesg, args);
559 fprintf (stderr, "\n");
560 + checkferror_output(stderr);
564 diff --git a/dc/stack.c b/dc/stack.c
565 index 0730e9c..5db3975 100644
569 #include "dc-regdef.h"
571 /* an oft-used error message: */
572 -#define Empty_Stack fprintf(stderr, "%s: stack empty\n", progname)
573 +#define Empty_Stack do{ \
574 + fprintf(stderr, "%s: stack empty\n", progname); \
575 + checkferror_output(stderr); \
579 /* simple linked-list implementation suffices: */
580 @@ -94,6 +97,7 @@ dc_binop DC_DECLARG((op, kscale))
581 if (dc_stack->value.dc_type!=DC_NUMBER
582 || dc_stack->link->value.dc_type!=DC_NUMBER){
583 fprintf(stderr, "%s: non-numeric value\n", progname);
584 + checkferror_output(stderr);
588 @@ -134,6 +138,7 @@ dc_binop2 DC_DECLARG((op, kscale))
589 if (dc_stack->value.dc_type!=DC_NUMBER
590 || dc_stack->link->value.dc_type!=DC_NUMBER){
591 fprintf(stderr, "%s: non-numeric value\n", progname);
592 + checkferror_output(stderr);
596 @@ -172,6 +177,7 @@ dc_cmpop DC_DECLVOID()
597 if (dc_stack->value.dc_type!=DC_NUMBER
598 || dc_stack->link->value.dc_type!=DC_NUMBER){
599 fprintf(stderr, "%s: non-numeric value\n", progname);
600 + checkferror_output(stderr);
604 @@ -209,6 +215,7 @@ dc_triop DC_DECLARG((op, kscale))
605 || dc_stack->link->value.dc_type!=DC_NUMBER
606 || dc_stack->link->link->value.dc_type!=DC_NUMBER){
607 fprintf(stderr, "%s: non-numeric value\n", progname);
608 + checkferror_output(stderr);
612 @@ -327,6 +334,7 @@ dc_register_get DC_DECLARG((regid, result))
613 r = dc_register[regid];
614 if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){
615 fprintf(stderr, "%s: register ", progname);
616 + checkferror_output(stderr);
617 dc_show_id(stderr, regid, " is empty\n");
620 @@ -401,6 +409,7 @@ dc_register_pop DC_DECLARG((stackid, result))
621 r = dc_register[stackid];
623 fprintf(stderr, "%s: stack register ", progname);
624 + checkferror_output(stderr);
625 dc_show_id(stderr, stackid, " is empty\n");
628 diff --git a/dc/string.c b/dc/string.c
629 index ff1e7f1..e24092d 100644
632 @@ -101,6 +101,7 @@ dc_out_str DC_DECLARG((value, newline, discard_flag))
633 fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
634 if (newline == DC_WITHNL)
636 + checkferror_output(stdout);
637 if (discard_flag == DC_TOSS)
640 @@ -176,6 +177,7 @@ dc_readstring DC_DECLARG((fp, ldelim, rdelim))
644 + checkferror_input(fp);
645 return dc_makestring(line_buf, (size_t)(p-line_buf));
648 diff --git a/h/number.h b/h/number.h
649 index 9b034b6..3a00a92 100644
652 @@ -150,4 +150,7 @@ _PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
653 _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
656 +_PROTOTYPE(void checkferror_input, (FILE*));
657 +_PROTOTYPE(void checkferror_output, (FILE*));
660 diff --git a/lib/number.c b/lib/number.c
661 index e211840..4d3ce46 100644
664 @@ -1776,6 +1776,7 @@ static void
668 + checkferror_output(stdout);
672 @@ -1785,6 +1786,7 @@ pn (num)
674 bc_out_num (num, 10, out_char, 0);
676 + checkferror_output(stdout);
680 @@ -1799,6 +1801,28 @@ pv (name, num, len)
681 printf ("%s=", name);
682 for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));
684 + checkferror_output(stdout);
689 +/* check ferror() status and if so die */
691 +checkferror_input (fp)
695 + perror("dc: could not read input file");
696 + exit(EXIT_FAILURE);
701 +checkferror_output (fp)
705 + perror("dc: could not write output file");
706 + exit(EXIT_FAILURE);