aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--awk.h1
-rw-r--r--builtin.c28
-rw-r--r--io.c52
4 files changed, 86 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index a9c7e555..35d73180 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2014-12-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ Enable non-fatal output on per-file or global basis,
+ via PROCINFO.
+
+ * awk.h (RED_NON_FATAL): New redirection flag.
+ * builtin.c (efwrite): If RED_NON_FATAL set, just set ERRNO and return.
+ (do_printf): Check errflg and if set, set ERRNO and return.
+ (do_print): Ditto.
+ (do_print_rec): Ditto.
+ * io.c (redflags2str): Update table.
+ (redirect): Check for global PROCINFO["nonfatal"] or for
+ PROCINFO[file, "nonfatal"] and don't fail on open if set.
+ Add RED_NON_FATAL to flags.
+ (in_PROCINFO): Make smarter and more general.
+
2014-12-12 Stephen Davies <sdavies@sdc.com.au>
Improve comment handling in pretty printing.
diff --git a/awk.h b/awk.h
index 41181529..ff3499cd 100644
--- a/awk.h
+++ b/awk.h
@@ -918,6 +918,7 @@ struct redirect {
# define RED_PTY 512
# define RED_SOCKET 1024
# define RED_TCP 2048
+# define RED_NON_FATAL 4096
char *value;
FILE *ifp; /* input fp, needed for PIPES_SIMULATED */
IOBUF *iop;
diff --git a/builtin.c b/builtin.c
index 21c6ed5c..b3f3f333 100644
--- a/builtin.c
+++ b/builtin.c
@@ -130,9 +130,12 @@ wrerror:
gawk_exit(EXIT_FATAL);
/* otherwise die verbosely */
- fatal(_("%s to \"%s\" failed (%s)"), from,
- rp ? rp->value : _("standard output"),
- errno ? strerror(errno) : _("reason unknown"));
+ if ((rp->flag & RED_NON_FATAL) != 0) {
+ update_ERRNO_int(errno);
+ } else
+ fatal(_("%s to \"%s\" failed (%s)"), from,
+ rp ? rp->value : _("standard output"),
+ errno ? strerror(errno) : _("reason unknown"));
}
/* do_exp --- exponential function */
@@ -1633,7 +1636,7 @@ do_printf(int nargs, int redirtype)
FILE *fp = NULL;
NODE *tmp;
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
NODE *redir_exp = NULL;
if (nargs == 0) {
@@ -1660,6 +1663,10 @@ do_printf(int nargs, int redirtype)
rp = redirect(redir_exp, redirtype, & errflg);
if (rp != NULL)
fp = rp->output.fp;
+ else if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
} else if (do_debug) /* only the debugger can change the default output */
fp = output_fp;
else
@@ -2072,7 +2079,7 @@ void
do_print(int nargs, int redirtype)
{
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
FILE *fp = NULL;
int i;
NODE *redir_exp = NULL;
@@ -2087,6 +2094,10 @@ do_print(int nargs, int redirtype)
rp = redirect(redir_exp, redirtype, & errflg);
if (rp != NULL)
fp = rp->output.fp;
+ else if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
} else if (do_debug) /* only the debugger can change the default output */
fp = output_fp;
else
@@ -2142,7 +2153,7 @@ do_print_rec(int nargs, int redirtype)
FILE *fp = NULL;
NODE *f0;
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
NODE *redir_exp = NULL;
assert(nargs == 0);
@@ -2162,6 +2173,11 @@ do_print_rec(int nargs, int redirtype)
if (! field0_valid)
(void) get_field(0L, NULL); /* rebuild record */
+ if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
+
f0 = fields_arr[0];
if (do_lint && (f0->flags & NULL_FIELD) != 0)
diff --git a/io.c b/io.c
index 1d15d887..b4688c89 100644
--- a/io.c
+++ b/io.c
@@ -718,6 +718,7 @@ redflags2str(int flags)
{ RED_PTY, "RED_PTY" },
{ RED_SOCKET, "RED_SOCKET" },
{ RED_TCP, "RED_TCP" },
+ { RED_NON_FATAL, "RED_NON_FATAL" },
{ 0, NULL }
};
@@ -744,6 +745,8 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
static struct redirect *save_rp = NULL; /* hold onto rp that should
* be freed for reuse
*/
+ bool is_output = false;
+ bool is_non_fatal = false;
if (do_sandbox)
fatal(_("redirection not allowed in sandbox mode"));
@@ -753,6 +756,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
tflag = RED_APPEND;
/* FALL THROUGH */
case redirect_output:
+ is_output = true;
outflag = (RED_FILE|RED_WRITE);
tflag |= outflag;
if (redirtype == redirect_output)
@@ -761,6 +765,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
what = ">>";
break;
case redirect_pipe:
+ is_output = true;
tflag = (RED_PIPE|RED_WRITE);
what = "|";
break;
@@ -773,6 +778,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
what = "<";
break;
case redirect_twoway:
+ is_output = true;
tflag = (RED_READ|RED_WRITE|RED_TWOWAY);
what = "|&";
break;
@@ -794,6 +800,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"),
str, what);
+ /* input files/pipes are automatically nonfatal */
+ if (is_output) {
+ is_non_fatal = (in_PROCINFO("nonfatal", NULL, NULL) != NULL
+ || in_PROCINFO(str, "nonfatal", NULL) != NULL);
+ if (is_non_fatal)
+ tflag |= RED_NON_FATAL;
+ }
+
#ifdef HAVE_SOCKETS
/*
* Use /inet4 to force IPv4, /inet6 to force IPv6, and plain
@@ -892,6 +906,12 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
(void) flush_io();
os_restore_mode(fileno(stdin));
+ /*
+ * Don't check is_non_fatal; see input pipe below.
+ * Note that the failure happens upon failure to fork,
+ * using a non-existant program will still succeed the
+ * popen().
+ */
if ((rp->output.fp = popen(str, binmode("w"))) == NULL)
fatal(_("can't open pipe `%s' for output (%s)"),
str, strerror(errno));
@@ -932,6 +952,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
*errflg = errno;
/* do not free rp, saving it for reuse (save_rp = rp) */
return NULL;
+ } else if (is_non_fatal) {
+ *errflg = errno;
+ /* do not free rp, saving it for reuse (save_rp = rp) */
+ return NULL;
} else
#endif
fatal(_("can't open two way pipe `%s' for input/output (%s)"),
@@ -1009,11 +1033,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
* can return -1. For output to file,
* complain. The shell will complain on
* a bad command to a pipe.
+ *
+ * 12/2014: Take nonfatal settings in PROCINFO into account.
*/
if (errflg != NULL)
*errflg = errno;
- if ( redirtype == redirect_output
- || redirtype == redirect_append) {
+ if (! is_non_fatal &&
+ (redirtype == redirect_output
+ || redirtype == redirect_append)) {
/* multiple messages make life easier for translators */
if (*direction == 'f')
fatal(_("can't redirect from `%s' (%s)"),
@@ -3799,12 +3826,21 @@ in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
NODE *r, *sub = NULL;
NODE *subsep = SUBSEP_node->var_value;
+ if (PROCINFO_node == NULL || (pidx1 == NULL && pidx2 == NULL))
+ return NULL;
+
/* full_idx is in+out parameter */
if (full_idx)
sub = *full_idx;
- str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2);
+ if (pidx1 != NULL && pidx2 == NULL)
+ str_len = strlen(pidx1);
+ else if (pidx1 == NULL && pidx2 != NULL)
+ str_len = strlen(pidx2);
+ else
+ str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2);
+
if (sub == NULL) {
emalloc(str, char *, str_len + 1, "in_PROCINFO");
sub = make_str_node(str, str_len, ALREADY_MALLOCED);
@@ -3818,8 +3854,14 @@ in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
sub->stlen = str_len;
}
- sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen,
- subsep->stptr, pidx2);
+ if (pidx1 != NULL && pidx2 == NULL)
+ strcpy(sub->stptr, pidx1);
+ else if (pidx1 == NULL && pidx2 != NULL)
+ strcpy(sub->stptr, pidx2);
+ else
+ sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen,
+ subsep->stptr, pidx2);
+
r = in_array(PROCINFO_node, sub);
if (! full_idx)
unref(sub);