diff options
-rw-r--r-- | ChangeLog | 26 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | builtin.c | 33 | ||||
-rw-r--r-- | doc/ChangeLog | 11 | ||||
-rw-r--r-- | doc/gawk.info | 445 | ||||
-rw-r--r-- | doc/gawk.texi | 18 | ||||
-rw-r--r-- | doc/gawktexi.in | 18 | ||||
-rw-r--r-- | io.c | 9 | ||||
-rw-r--r-- | test/ChangeLog | 15 | ||||
-rw-r--r-- | test/Makefile.am | 14 | ||||
-rw-r--r-- | test/Makefile.in | 39 | ||||
-rw-r--r-- | test/Maketests | 25 | ||||
-rw-r--r-- | test/clos1way2.awk | 6 | ||||
-rw-r--r-- | test/clos1way2.in | 1 | ||||
-rw-r--r-- | test/clos1way2.ok | 4 | ||||
-rw-r--r-- | test/clos1way3.awk | 7 | ||||
-rw-r--r-- | test/clos1way3.ok | 3 | ||||
-rw-r--r-- | test/clos1way4.awk | 7 | ||||
-rw-r--r-- | test/clos1way4.ok | 3 | ||||
-rw-r--r-- | test/clos1way5.awk | 9 | ||||
-rw-r--r-- | test/clos1way5.ok | 3 | ||||
-rw-r--r-- | test/clos1way6.awk | 7 | ||||
-rw-r--r-- | test/clos1way6.ok | 3 |
23 files changed, 489 insertions, 221 deletions
@@ -1,3 +1,29 @@ +2016-04-06 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_printf): Allow a write to the closed write-end of + a two-way pipe to be nonfatal if NONFATAL is set for it. + (do_print): Ditto. + (do_print_rec): Ditto. + * io.c (do_getline_redir): Same thing for reading from a closed + read end of a two-way pipe. Fatal error. + +2016-04-04 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_fflush): Add warning for flush to two-way + pipe where write end was closed. + * io.c (flush_io): Add some braces for the for loop. + +2016-04-02 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_printf): If the redirection is two way but the + fp is NULL, it means we're writing to the closed write-end of + a two-way pipe. Issue a fatal error message. + (do_print): Ditto. + (do_print_rec): Ditto. + * io.c (do_getline_redir): Same thing for reading from a closed + read end of a two-way pipe. Fatal error. + * NEWS: Updated. + 2016-03-27 Stephen Davies <sdavies@sdc.com.au> * awkgram.y (get_comment): Strip CRs from comment. Strip @@ -103,6 +103,10 @@ Changes from 4.1.3 to 4.1.x 8. The return value of system() has been enhanced to convey more information. See the doc. +9. Attempting to write to the "to" end of a two-way pipe that has been + closed is now a fatal error. Similarly, so is reading from the "from" + end that has been closed. + Changes from 4.1.2 to 4.1.3 --------------------------- @@ -241,6 +241,9 @@ do_fflush(int nargs) fp = rp->output.fp; if (fp != NULL) status = rp->output.gawk_fflush(fp, rp->output.opaque); + else if ((rp->flag & RED_TWOWAY) != 0) + warning(_("fflush: cannot flush: two-way pipe `%s' has closed write end"), + file); } else if ((fp = stdfile(tmp->stptr, tmp->stlen)) != NULL) { status = fflush(fp); } else { @@ -1674,8 +1677,16 @@ do_printf(int nargs, int redirtype) if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); rp = redirect(redir_exp, redirtype, & errflg, true); - if (rp != NULL) + if (rp != NULL) { + if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return; + } + fatal(_("printf: attempt to write to closed write end of two-way pipe")); + } fp = rp->output.fp; + } else if (errflg) { update_ERRNO_int(errflg); return; @@ -2150,8 +2161,16 @@ do_print(int nargs, int redirtype) if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); rp = redirect(redir_exp, redirtype, & errflg, true); - if (rp != NULL) + if (rp != NULL) { + if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return; + } + fatal(_("print: attempt to write to closed write end of two-way pipe")); + } fp = rp->output.fp; + } else if (errflg) { update_ERRNO_int(errflg); return; @@ -2220,8 +2239,16 @@ do_print_rec(int nargs, int redirtype) if (redirtype != 0) { redir_exp = TOP(); rp = redirect(redir_exp, redirtype, & errflg, true); - if (rp != NULL) + if (rp != NULL) { + if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return; + } + fatal(_("print: attempt to write to closed write end of two-way pipe")); + } fp = rp->output.fp; + } DEREF(redir_exp); decr_sp(); } else diff --git a/doc/ChangeLog b/doc/ChangeLog index 9fe1a706..7ea2afe0 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,8 +1,19 @@ +2016-04-06 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Two-way I/O): Document that writing to the closed + write end of a two way pipe or reading from the closed read end + can be made nonfatal. + 2016-04-04 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in, gawkinet.texi: Enable use of braces in indexes. Requires Texinfo 6.0 or later. +2016-04-02 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Two-way I/O): Document that closing the "from" + end waits for the process to exit, so it's not such a great idea. + 2016-03-27 Arnold D. Robbins <arnold@skeeve.com> * gawkinet.texi: Small update about end of line vs full diff --git a/doc/gawk.info b/doc/gawk.info index c1e44de8..16f06d4c 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -19938,6 +19938,21 @@ the coprocess and exits. ensures traditional Unix (ASCII) sorting from 'sort'. This is not strictly necessary here, but it's good to know how to do this. + Be careful when closing the '"from"' end of a two-way pipe; in this +case 'gawk' waits for the child process to exit, which may cause your +program to hang. (Thus, this particular feature is of much less use in +practice than being able to close the '"to"' end.) + + CAUTION: Normally, it is a fatal error to write to the '"to"' end + of a two-way pipe which has been closed, and it is also a fatal + error to read from the '"from"' end of a two-way pipe that has been + closed. + + You may set 'PROCINFO["COMMAND", "NONFATAL"]' to make such + operations become nonfatal, in which case you then need to check + 'ERRNO' after each 'print', 'printf', or 'getline'. *Note + Nonfatal::, for more information. + You may also use pseudo-ttys (ptys) for two-way communication instead of pipes, if your system supports them. This is done on a per-command basis, by setting a special element in the 'PROCINFO' array (*note @@ -33738,7 +33753,7 @@ Index * gawk, predefined variables and: Built-in Variables. (line 14) * gawk, PROCINFO array in: Auto-set. (line 148) * gawk, PROCINFO array in <1>: Time Functions. (line 47) -* gawk, PROCINFO array in <2>: Two-way I/O. (line 99) +* gawk, PROCINFO array in <2>: Two-way I/O. (line 114) * gawk, regexp constants and: Using Constant Regexps. (line 28) * gawk, regular expressions, case sensitivity: Case-sensitivity. @@ -34516,7 +34531,7 @@ Index * PROCINFO array: Auto-set. (line 148) * PROCINFO array <1>: Time Functions. (line 47) * PROCINFO array <2>: Passwd Functions. (line 6) -* PROCINFO array, and communications via ptys: Two-way I/O. (line 99) +* PROCINFO array, and communications via ptys: Two-way I/O. (line 114) * PROCINFO array, and group membership: Group Functions. (line 6) * PROCINFO array, and user and group ID numbers: Id Program. (line 15) * PROCINFO array, testing the field splitting: Passwd Functions. @@ -35585,218 +35600,218 @@ Ref: Controlling Array Traversal-Footnote-1801827 Node: Array Sorting Functions801945 Ref: Array Sorting Functions-Footnote-1807036 Node: Two-way I/O807232 -Ref: Two-way I/O-Footnote-1813052 -Ref: Two-way I/O-Footnote-2813239 -Node: TCP/IP Networking813321 -Node: Profiling816439 -Ref: Profiling-Footnote-1824932 -Node: Advanced Features Summary825255 -Node: Internationalization827099 -Node: I18N and L10N828579 -Node: Explaining gettext829266 -Ref: Explaining gettext-Footnote-1834289 -Ref: Explaining gettext-Footnote-2834474 -Node: Programmer i18n834639 -Ref: Programmer i18n-Footnote-1839494 -Node: Translator i18n839543 -Node: String Extraction840337 -Ref: String Extraction-Footnote-1841469 -Node: Printf Ordering841555 -Ref: Printf Ordering-Footnote-1844341 -Node: I18N Portability844405 -Ref: I18N Portability-Footnote-1846861 -Node: I18N Example846924 -Ref: I18N Example-Footnote-1849730 -Node: Gawk I18N849803 -Node: I18N Summary850448 -Node: Debugger851789 -Node: Debugging852811 -Node: Debugging Concepts853252 -Node: Debugging Terms855061 -Node: Awk Debugging857636 -Node: Sample Debugging Session858542 -Node: Debugger Invocation859076 -Node: Finding The Bug860462 -Node: List of Debugger Commands866940 -Node: Breakpoint Control868273 -Node: Debugger Execution Control871967 -Node: Viewing And Changing Data875329 -Node: Execution Stack878703 -Node: Debugger Info880340 -Node: Miscellaneous Debugger Commands884411 -Node: Readline Support889499 -Node: Limitations890395 -Ref: Limitations-Footnote-1894626 -Node: Debugging Summary894677 -Node: Arbitrary Precision Arithmetic895956 -Node: Computer Arithmetic897372 -Ref: table-numeric-ranges900963 -Ref: Computer Arithmetic-Footnote-1901685 -Node: Math Definitions901742 -Ref: table-ieee-formats905056 -Ref: Math Definitions-Footnote-1905659 -Node: MPFR features905764 -Node: FP Math Caution907481 -Ref: FP Math Caution-Footnote-1908553 -Node: Inexactness of computations908922 -Node: Inexact representation909882 -Node: Comparing FP Values911242 -Node: Errors accumulate912324 -Node: Getting Accuracy913757 -Node: Try To Round916467 -Node: Setting precision917366 -Ref: table-predefined-precision-strings918063 -Node: Setting the rounding mode919893 -Ref: table-gawk-rounding-modes920267 -Ref: Setting the rounding mode-Footnote-1923675 -Node: Arbitrary Precision Integers923854 -Ref: Arbitrary Precision Integers-Footnote-1928771 -Node: POSIX Floating Point Problems928920 -Ref: POSIX Floating Point Problems-Footnote-1932802 -Node: Floating point summary932840 -Node: Dynamic Extensions935030 -Node: Extension Intro936583 -Node: Plugin License937849 -Node: Extension Mechanism Outline938646 -Ref: figure-load-extension939085 -Ref: figure-register-new-function940650 -Ref: figure-call-new-function941742 -Node: Extension API Description943804 -Node: Extension API Functions Introduction945336 -Node: General Data Types950195 -Ref: General Data Types-Footnote-1956150 -Node: Memory Allocation Functions956449 -Ref: Memory Allocation Functions-Footnote-1959294 -Node: Constructor Functions959393 -Node: Registration Functions961138 -Node: Extension Functions961823 -Node: Exit Callback Functions964122 -Node: Extension Version String965372 -Node: Input Parsers966035 -Node: Output Wrappers975920 -Node: Two-way processors980432 -Node: Printing Messages982696 -Ref: Printing Messages-Footnote-1983770 -Node: Updating ERRNO983923 -Node: Requesting Values984662 -Ref: table-value-types-returned985399 -Node: Accessing Parameters986282 -Node: Symbol Table Access987517 -Node: Symbol table by name988029 -Node: Symbol table by cookie990050 -Ref: Symbol table by cookie-Footnote-1994199 -Node: Cached values994263 -Ref: Cached values-Footnote-1997764 -Node: Array Manipulation997855 -Ref: Array Manipulation-Footnote-1998946 -Node: Array Data Types998983 -Ref: Array Data Types-Footnote-11001641 -Node: Array Functions1001733 -Node: Flattening Arrays1005591 -Node: Creating Arrays1012499 -Node: Redirection API1017270 -Node: Extension API Variables1020101 -Node: Extension Versioning1020734 -Node: Extension API Informational Variables1022625 -Node: Extension API Boilerplate1023689 -Node: Finding Extensions1027503 -Node: Extension Example1028062 -Node: Internal File Description1028860 -Node: Internal File Ops1032940 -Ref: Internal File Ops-Footnote-11044702 -Node: Using Internal File Ops1044842 -Ref: Using Internal File Ops-Footnote-11047225 -Node: Extension Samples1047499 -Node: Extension Sample File Functions1049028 -Node: Extension Sample Fnmatch1056677 -Node: Extension Sample Fork1058164 -Node: Extension Sample Inplace1059382 -Node: Extension Sample Ord1062592 -Node: Extension Sample Readdir1063428 -Ref: table-readdir-file-types1064317 -Node: Extension Sample Revout1065122 -Node: Extension Sample Rev2way1065711 -Node: Extension Sample Read write array1066451 -Node: Extension Sample Readfile1068393 -Node: Extension Sample Time1069488 -Node: Extension Sample API Tests1070836 -Node: gawkextlib1071328 -Node: Extension summary1073775 -Node: Extension Exercises1077467 -Node: Language History1078964 -Node: V7/SVR3.11080620 -Node: SVR41082772 -Node: POSIX1084206 -Node: BTL1085585 -Node: POSIX/GNU1086314 -Node: Feature History1092176 -Node: Common Extensions1106546 -Node: Ranges and Locales1107829 -Ref: Ranges and Locales-Footnote-11112445 -Ref: Ranges and Locales-Footnote-21112472 -Ref: Ranges and Locales-Footnote-31112707 -Node: Contributors1112928 -Node: History summary1118497 -Node: Installation1119877 -Node: Gawk Distribution1120821 -Node: Getting1121305 -Node: Extracting1122266 -Node: Distribution contents1123904 -Node: Unix Installation1129998 -Node: Quick Installation1130680 -Node: Shell Startup Files1133094 -Node: Additional Configuration Options1134172 -Node: Configuration Philosophy1135977 -Node: Non-Unix Installation1138346 -Node: PC Installation1138804 -Node: PC Binary Installation1140124 -Node: PC Compiling1141976 -Ref: PC Compiling-Footnote-11145000 -Node: PC Testing1145109 -Node: PC Using1146289 -Node: Cygwin1150403 -Node: MSYS1151173 -Node: VMS Installation1151674 -Node: VMS Compilation1152465 -Ref: VMS Compilation-Footnote-11153694 -Node: VMS Dynamic Extensions1153752 -Node: VMS Installation Details1155437 -Node: VMS Running1157690 -Node: VMS GNV1161969 -Node: VMS Old Gawk1162704 -Node: Bugs1163175 -Node: Other Versions1167372 -Node: Installation summary1173956 -Node: Notes1175014 -Node: Compatibility Mode1175879 -Node: Additions1176661 -Node: Accessing The Source1177586 -Node: Adding Code1179021 -Node: New Ports1185240 -Node: Derived Files1189728 -Ref: Derived Files-Footnote-11195213 -Ref: Derived Files-Footnote-21195248 -Ref: Derived Files-Footnote-31195846 -Node: Future Extensions1195960 -Node: Implementation Limitations1196618 -Node: Extension Design1197801 -Node: Old Extension Problems1198955 -Ref: Old Extension Problems-Footnote-11200473 -Node: Extension New Mechanism Goals1200530 -Ref: Extension New Mechanism Goals-Footnote-11203894 -Node: Extension Other Design Decisions1204083 -Node: Extension Future Growth1206196 -Node: Old Extension Mechanism1207032 -Node: Notes summary1208795 -Node: Basic Concepts1209977 -Node: Basic High Level1210658 -Ref: figure-general-flow1210940 -Ref: figure-process-flow1211625 -Ref: Basic High Level-Footnote-11214926 -Node: Basic Data Typing1215111 -Node: Glossary1218439 -Node: Copying1250385 -Node: GNU Free Documentation License1287924 -Node: Index1313042 +Ref: Two-way I/O-Footnote-1813782 +Ref: Two-way I/O-Footnote-2813969 +Node: TCP/IP Networking814051 +Node: Profiling817169 +Ref: Profiling-Footnote-1825662 +Node: Advanced Features Summary825985 +Node: Internationalization827829 +Node: I18N and L10N829309 +Node: Explaining gettext829996 +Ref: Explaining gettext-Footnote-1835019 +Ref: Explaining gettext-Footnote-2835204 +Node: Programmer i18n835369 +Ref: Programmer i18n-Footnote-1840224 +Node: Translator i18n840273 +Node: String Extraction841067 +Ref: String Extraction-Footnote-1842199 +Node: Printf Ordering842285 +Ref: Printf Ordering-Footnote-1845071 +Node: I18N Portability845135 +Ref: I18N Portability-Footnote-1847591 +Node: I18N Example847654 +Ref: I18N Example-Footnote-1850460 +Node: Gawk I18N850533 +Node: I18N Summary851178 +Node: Debugger852519 +Node: Debugging853541 +Node: Debugging Concepts853982 +Node: Debugging Terms855791 +Node: Awk Debugging858366 +Node: Sample Debugging Session859272 +Node: Debugger Invocation859806 +Node: Finding The Bug861192 +Node: List of Debugger Commands867670 +Node: Breakpoint Control869003 +Node: Debugger Execution Control872697 +Node: Viewing And Changing Data876059 +Node: Execution Stack879433 +Node: Debugger Info881070 +Node: Miscellaneous Debugger Commands885141 +Node: Readline Support890229 +Node: Limitations891125 +Ref: Limitations-Footnote-1895356 +Node: Debugging Summary895407 +Node: Arbitrary Precision Arithmetic896686 +Node: Computer Arithmetic898102 +Ref: table-numeric-ranges901693 +Ref: Computer Arithmetic-Footnote-1902415 +Node: Math Definitions902472 +Ref: table-ieee-formats905786 +Ref: Math Definitions-Footnote-1906389 +Node: MPFR features906494 +Node: FP Math Caution908211 +Ref: FP Math Caution-Footnote-1909283 +Node: Inexactness of computations909652 +Node: Inexact representation910612 +Node: Comparing FP Values911972 +Node: Errors accumulate913054 +Node: Getting Accuracy914487 +Node: Try To Round917197 +Node: Setting precision918096 +Ref: table-predefined-precision-strings918793 +Node: Setting the rounding mode920623 +Ref: table-gawk-rounding-modes920997 +Ref: Setting the rounding mode-Footnote-1924405 +Node: Arbitrary Precision Integers924584 +Ref: Arbitrary Precision Integers-Footnote-1929501 +Node: POSIX Floating Point Problems929650 +Ref: POSIX Floating Point Problems-Footnote-1933532 +Node: Floating point summary933570 +Node: Dynamic Extensions935760 +Node: Extension Intro937313 +Node: Plugin License938579 +Node: Extension Mechanism Outline939376 +Ref: figure-load-extension939815 +Ref: figure-register-new-function941380 +Ref: figure-call-new-function942472 +Node: Extension API Description944534 +Node: Extension API Functions Introduction946066 +Node: General Data Types950925 +Ref: General Data Types-Footnote-1956880 +Node: Memory Allocation Functions957179 +Ref: Memory Allocation Functions-Footnote-1960024 +Node: Constructor Functions960123 +Node: Registration Functions961868 +Node: Extension Functions962553 +Node: Exit Callback Functions964852 +Node: Extension Version String966102 +Node: Input Parsers966765 +Node: Output Wrappers976650 +Node: Two-way processors981162 +Node: Printing Messages983426 +Ref: Printing Messages-Footnote-1984500 +Node: Updating ERRNO984653 +Node: Requesting Values985392 +Ref: table-value-types-returned986129 +Node: Accessing Parameters987012 +Node: Symbol Table Access988247 +Node: Symbol table by name988759 +Node: Symbol table by cookie990780 +Ref: Symbol table by cookie-Footnote-1994929 +Node: Cached values994993 +Ref: Cached values-Footnote-1998494 +Node: Array Manipulation998585 +Ref: Array Manipulation-Footnote-1999676 +Node: Array Data Types999713 +Ref: Array Data Types-Footnote-11002371 +Node: Array Functions1002463 +Node: Flattening Arrays1006321 +Node: Creating Arrays1013229 +Node: Redirection API1018000 +Node: Extension API Variables1020831 +Node: Extension Versioning1021464 +Node: Extension API Informational Variables1023355 +Node: Extension API Boilerplate1024419 +Node: Finding Extensions1028233 +Node: Extension Example1028792 +Node: Internal File Description1029590 +Node: Internal File Ops1033670 +Ref: Internal File Ops-Footnote-11045432 +Node: Using Internal File Ops1045572 +Ref: Using Internal File Ops-Footnote-11047955 +Node: Extension Samples1048229 +Node: Extension Sample File Functions1049758 +Node: Extension Sample Fnmatch1057407 +Node: Extension Sample Fork1058894 +Node: Extension Sample Inplace1060112 +Node: Extension Sample Ord1063322 +Node: Extension Sample Readdir1064158 +Ref: table-readdir-file-types1065047 +Node: Extension Sample Revout1065852 +Node: Extension Sample Rev2way1066441 +Node: Extension Sample Read write array1067181 +Node: Extension Sample Readfile1069123 +Node: Extension Sample Time1070218 +Node: Extension Sample API Tests1071566 +Node: gawkextlib1072058 +Node: Extension summary1074505 +Node: Extension Exercises1078197 +Node: Language History1079694 +Node: V7/SVR3.11081350 +Node: SVR41083502 +Node: POSIX1084936 +Node: BTL1086315 +Node: POSIX/GNU1087044 +Node: Feature History1092906 +Node: Common Extensions1107276 +Node: Ranges and Locales1108559 +Ref: Ranges and Locales-Footnote-11113175 +Ref: Ranges and Locales-Footnote-21113202 +Ref: Ranges and Locales-Footnote-31113437 +Node: Contributors1113658 +Node: History summary1119227 +Node: Installation1120607 +Node: Gawk Distribution1121551 +Node: Getting1122035 +Node: Extracting1122996 +Node: Distribution contents1124634 +Node: Unix Installation1130728 +Node: Quick Installation1131410 +Node: Shell Startup Files1133824 +Node: Additional Configuration Options1134902 +Node: Configuration Philosophy1136707 +Node: Non-Unix Installation1139076 +Node: PC Installation1139534 +Node: PC Binary Installation1140854 +Node: PC Compiling1142706 +Ref: PC Compiling-Footnote-11145730 +Node: PC Testing1145839 +Node: PC Using1147019 +Node: Cygwin1151133 +Node: MSYS1151903 +Node: VMS Installation1152404 +Node: VMS Compilation1153195 +Ref: VMS Compilation-Footnote-11154424 +Node: VMS Dynamic Extensions1154482 +Node: VMS Installation Details1156167 +Node: VMS Running1158420 +Node: VMS GNV1162699 +Node: VMS Old Gawk1163434 +Node: Bugs1163905 +Node: Other Versions1168102 +Node: Installation summary1174686 +Node: Notes1175744 +Node: Compatibility Mode1176609 +Node: Additions1177391 +Node: Accessing The Source1178316 +Node: Adding Code1179751 +Node: New Ports1185970 +Node: Derived Files1190458 +Ref: Derived Files-Footnote-11195943 +Ref: Derived Files-Footnote-21195978 +Ref: Derived Files-Footnote-31196576 +Node: Future Extensions1196690 +Node: Implementation Limitations1197348 +Node: Extension Design1198531 +Node: Old Extension Problems1199685 +Ref: Old Extension Problems-Footnote-11201203 +Node: Extension New Mechanism Goals1201260 +Ref: Extension New Mechanism Goals-Footnote-11204624 +Node: Extension Other Design Decisions1204813 +Node: Extension Future Growth1206926 +Node: Old Extension Mechanism1207762 +Node: Notes summary1209525 +Node: Basic Concepts1210707 +Node: Basic High Level1211388 +Ref: figure-general-flow1211670 +Ref: figure-process-flow1212355 +Ref: Basic High Level-Footnote-11215656 +Node: Basic Data Typing1215841 +Node: Glossary1219169 +Node: Copying1251115 +Node: GNU Free Documentation License1288654 +Node: Index1313772 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index 23a25298..fd71dbc9 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -27853,6 +27853,24 @@ As a side note, the assignment @samp{LC_ALL=C} in the @command{sort} command ensures traditional Unix (ASCII) sorting from @command{sort}. This is not strictly necessary here, but it's good to know how to do this. +Be careful when closing the @code{"from"} end of a two-way pipe; in this +case @command{gawk} waits for the child process to exit, which may cause +your program to hang. (Thus, this particular feature is of much less +use in practice than being able to close the @code{"to"} end.) + +@quotation CAUTION +Normally, +it is a fatal error to write to the @code{"to"} end of a two-way +pipe which has been closed, and it is also a fatal error to read +from the @code{"from"} end of a two-way pipe that has been closed. + +You may set @code{PROCINFO["@var{command}", "NONFATAL"]} to +make such operations become nonfatal, in which case you then need +to check @code{ERRNO} after each @code{print}, @code{printf}, +or @code{getline}. +@xref{Nonfatal}, for more information. +@end quotation + @cindex @command{gawk}, @code{PROCINFO} array in @cindex @code{PROCINFO} array, and communications via ptys You may also use pseudo-ttys (ptys) for diff --git a/doc/gawktexi.in b/doc/gawktexi.in index e43d7137..f47c8459 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -26944,6 +26944,24 @@ As a side note, the assignment @samp{LC_ALL=C} in the @command{sort} command ensures traditional Unix (ASCII) sorting from @command{sort}. This is not strictly necessary here, but it's good to know how to do this. +Be careful when closing the @code{"from"} end of a two-way pipe; in this +case @command{gawk} waits for the child process to exit, which may cause +your program to hang. (Thus, this particular feature is of much less +use in practice than being able to close the @code{"to"} end.) + +@quotation CAUTION +Normally, +it is a fatal error to write to the @code{"to"} end of a two-way +pipe which has been closed, and it is also a fatal error to read +from the @code{"from"} end of a two-way pipe that has been closed. + +You may set @code{PROCINFO["@var{command}", "NONFATAL"]} to +make such operations become nonfatal, in which case you then need +to check @code{ERRNO} after each @code{print}, @code{printf}, +or @code{getline}. +@xref{Nonfatal}, for more information. +@end quotation + @cindex @command{gawk}, @code{PROCINFO} array in @cindex @code{PROCINFO} array, and communications via ptys You may also use pseudo-ttys (ptys) for @@ -1391,7 +1391,7 @@ flush_io() warning(_("error writing standard error (%s)"), strerror(errno)); status++; } - for (rp = red_head; rp != NULL; rp = rp->next) + for (rp = red_head; rp != NULL; rp = rp->next) { /* flush both files and pipes, what the heck */ if ((rp->flag & RED_WRITE) != 0 && rp->output.fp != NULL) { if (rp->output.gawk_fflush(rp->output.fp, rp->output.opaque)) { @@ -1407,6 +1407,7 @@ flush_io() status++; } } + } if (status != 0) status = -1; /* canonicalize it */ return status; @@ -2602,6 +2603,12 @@ do_getline_redir(int into_variable, enum redirval redirtype) update_ERRNO_int(redir_error); } return make_number((AWKNUM) -1.0); + } else if ((rp->flag & RED_TWOWAY) != 0 && rp->iop == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return make_number((AWKNUM) -1.0); + } + fatal(_("getline: attempt to read from closed read end of two-way pipe")); } iop = rp->iop; if (iop == NULL) /* end of input */ diff --git a/test/ChangeLog b/test/ChangeLog index 2b44b4b5..bfb05de6 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,18 @@ +2016-04-06 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (clos1way6): New test. + * clos1way6.awk, clos1way6.ok: New files. + +2016-04-04 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (clos1way2, clos1way3, clos1way4, clos1way5): + New tests. + * clos1way2.awk, clos1way2.in, clos1way2.ok, clos1way3.awk, + clos1way3.ok, clos1way4.awk, clos1way4.ok, clos1way5.awk, + clos1way5.ok: New files. + * clos1way2.awk: Add call to fflush() to test it too. + * clos1way2.ok: Updated after code change. + 2016-03-27 Arnold D. Robbins <arnold@skeeve.com> * profile5.ok: Adjust after code changes. diff --git a/test/Makefile.am b/test/Makefile.am index 776dfbd0..fdb163d7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -147,6 +147,17 @@ EXTRA_DIST = \ clobber.ok \ clos1way.awk \ clos1way.ok \ + clos1way2.awk \ + clos1way2.in \ + clos1way2.ok \ + clos1way3.awk \ + clos1way3.ok \ + clos1way4.awk \ + clos1way4.ok \ + clos1way5.awk \ + clos1way5.ok \ + clos1way6.awk \ + clos1way6.ok \ closebad.awk \ closebad.ok \ clsflnam.awk \ @@ -1121,7 +1132,8 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \ + colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 clos1way6 \ + crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \ devfd devfd1 devfd2 dumpvars errno exit \ fieldwdth fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ diff --git a/test/Makefile.in b/test/Makefile.in index 7c3a5a00..3fa8fbc4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -404,6 +404,17 @@ EXTRA_DIST = \ clobber.ok \ clos1way.awk \ clos1way.ok \ + clos1way2.awk \ + clos1way2.in \ + clos1way2.ok \ + clos1way3.awk \ + clos1way3.ok \ + clos1way4.awk \ + clos1way4.ok \ + clos1way5.awk \ + clos1way5.ok \ + clos1way6.awk \ + clos1way6.ok \ closebad.awk \ closebad.ok \ clsflnam.awk \ @@ -1377,7 +1388,8 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \ + colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 clos1way6 \ + crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \ devfd devfd1 devfd2 dumpvars errno exit \ fieldwdth fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ @@ -3648,6 +3660,31 @@ backw: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +clos1way2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way4: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way5: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way6: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + crlf: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ diff --git a/test/Maketests b/test/Maketests index f1ffdf97..3b4691d2 100644 --- a/test/Maketests +++ b/test/Maketests @@ -997,6 +997,31 @@ backw: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +clos1way2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way4: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way5: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +clos1way6: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + crlf: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ diff --git a/test/clos1way2.awk b/test/clos1way2.awk new file mode 100644 index 00000000..5794bec5 --- /dev/null +++ b/test/clos1way2.awk @@ -0,0 +1,6 @@ +{ + cmd = "cat - 1>&2; sleep 2" + print |& cmd; close(cmd, "to") + fflush(cmd) + print |& cmd; print ERRNO +} diff --git a/test/clos1way2.in b/test/clos1way2.in new file mode 100644 index 00000000..9daeafb9 --- /dev/null +++ b/test/clos1way2.in @@ -0,0 +1 @@ +test diff --git a/test/clos1way2.ok b/test/clos1way2.ok new file mode 100644 index 00000000..063c4213 --- /dev/null +++ b/test/clos1way2.ok @@ -0,0 +1,4 @@ +gawk: clos1way2.awk:4: (FILENAME=- FNR=1) warning: fflush: cannot flush: two-way pipe `cat - 1>&2; sleep 2' has closed write end +gawk: clos1way2.awk:5: (FILENAME=- FNR=1) fatal: print: attempt to write to closed write end of two-way pipe +test +CODE: 2 diff --git a/test/clos1way3.awk b/test/clos1way3.awk new file mode 100644 index 00000000..f69f6675 --- /dev/null +++ b/test/clos1way3.awk @@ -0,0 +1,7 @@ +BEGIN { + cmd = "cat - 1>&2; sleep 2" + print "test1" |& cmd + close(cmd, "to") + print "test2" |& cmd + print ERRNO +} diff --git a/test/clos1way3.ok b/test/clos1way3.ok new file mode 100644 index 00000000..74f67738 --- /dev/null +++ b/test/clos1way3.ok @@ -0,0 +1,3 @@ +gawk: clos1way3.awk:5: fatal: print: attempt to write to closed write end of two-way pipe +test1 +ODE: 2 diff --git a/test/clos1way4.awk b/test/clos1way4.awk new file mode 100644 index 00000000..6c68c5c8 --- /dev/null +++ b/test/clos1way4.awk @@ -0,0 +1,7 @@ +BEGIN { + cmd = "cat - 1>&2; sleep 2" + printf "%s\n", "test1" |& cmd + close(cmd, "to") + printf "%s\n", "test2" |& cmd + print ERRNO +} diff --git a/test/clos1way4.ok b/test/clos1way4.ok new file mode 100644 index 00000000..707f9813 --- /dev/null +++ b/test/clos1way4.ok @@ -0,0 +1,3 @@ +gawk: clos1way4.awk:5: fatal: printf: attempt to write to closed write end of two-way pipe +test1 +ODE: 2 diff --git a/test/clos1way5.awk b/test/clos1way5.awk new file mode 100644 index 00000000..ca1bd94c --- /dev/null +++ b/test/clos1way5.awk @@ -0,0 +1,9 @@ +BEGIN { + cmd = "echo test1; echo test2; sleep 2" + cmd |& getline x + print x + close(cmd, "from") + cmd |& getline x + print x + print ERRNO +} diff --git a/test/clos1way5.ok b/test/clos1way5.ok new file mode 100644 index 00000000..1ff15402 --- /dev/null +++ b/test/clos1way5.ok @@ -0,0 +1,3 @@ +test1 +gawk: clos1way5.awk:6: fatal: getline: attempt to read from closed read end of two-way pipe +EXIT CODE: 2 diff --git a/test/clos1way6.awk b/test/clos1way6.awk new file mode 100644 index 00000000..19779d73 --- /dev/null +++ b/test/clos1way6.awk @@ -0,0 +1,7 @@ +BEGIN { + cmd = "cat - 1>&2; sleep 2" + PROCINFO[cmd, "NONFATAL"] = 1 + print "test1" |& cmd; close(cmd, "to") + fflush(cmd) + print "test2" |& cmd; print ERRNO +} diff --git a/test/clos1way6.ok b/test/clos1way6.ok new file mode 100644 index 00000000..5768617d --- /dev/null +++ b/test/clos1way6.ok @@ -0,0 +1,3 @@ +gawk: clos1way6.awk:5: warning: fflush: cannot flush: two-way pipe `cat - 1>&2; sleep 2' has closed write end +test1 +Bad file descriptor |