diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2014-12-20 19:56:44 +0200 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2014-12-20 19:56:44 +0200 |
commit | dcaab6dd8a28be8885ccc508c49b962a61ab09fe (patch) | |
tree | d356ce9e648e08c7c70ea6682809cf8c2c9ad738 | |
parent | 0d52289482d468c8566976d77c0c6a6a4e602add (diff) | |
download | egawk-dcaab6dd8a28be8885ccc508c49b962a61ab09fe.tar.gz egawk-dcaab6dd8a28be8885ccc508c49b962a61ab09fe.tar.bz2 egawk-dcaab6dd8a28be8885ccc508c49b962a61ab09fe.zip |
Start at non-fatal output via PROCINFO.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | awk.h | 1 | ||||
-rw-r--r-- | builtin.c | 28 | ||||
-rw-r--r-- | io.c | 52 |
4 files changed, 86 insertions, 11 deletions
@@ -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. @@ -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; @@ -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) @@ -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); |