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

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