0002-notice-read-and-write-errors-on-input-and-output.patch 20 KB

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