From 6959e2ab216aeb1d5d8f07ce73cd8b9894b83006 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 30 Jun 2013 20:57:03 -0400 Subject: Added first version of select extension and new API hooks needed by it. --- io.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index dc41aea3..14b8df91 100644 --- a/io.c +++ b/io.c @@ -686,10 +686,9 @@ redflags2str(int flags) /* redirect --- Redirection for printf and print commands */ struct redirect * -redirect(NODE *redir_exp, int redirtype, int *errflg) +redirect_string(char *str, size_t explen, int not_string, int redirtype, int *errflg) { struct redirect *rp; - char *str; int tflag = 0; int outflag = 0; const char *direction = "to"; @@ -736,18 +735,16 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) default: cant_happen(); } - if (do_lint && (redir_exp->flags & STRCUR) == 0) + if (do_lint && not_string) lintwarn(_("expression in `%s' redirection only has numeric value"), what); - redir_exp = force_string(redir_exp); - str = redir_exp->stptr; if (str == NULL || *str == '\0') fatal(_("expression for `%s' redirection has null string value"), what); - if (do_lint && (strncmp(str, "0", redir_exp->stlen) == 0 - || strncmp(str, "1", redir_exp->stlen) == 0)) + if (do_lint && (strncmp(str, "0", explen) == 0 + || strncmp(str, "1", explen) == 0)) lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"), str, what); @@ -785,8 +782,8 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) #endif /* PIPES_SIMULATED */ /* now check for a match */ - if (strlen(rp->value) == redir_exp->stlen - && memcmp(rp->value, str, redir_exp->stlen) == 0 + if (strlen(rp->value) == explen + && memcmp(rp->value, str, explen) == 0 && ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag || (outflag != 0 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) { @@ -797,22 +794,24 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) if (do_lint && rpflag != newflag) lintwarn( _("unnecessary mixing of `>' and `>>' for file `%.*s'"), - (int) redir_exp->stlen, rp->value); + (int) explen, rp->value); break; } } if (rp == NULL) { + char *newstr; new_rp = true; if (save_rp != NULL) { rp = save_rp; efree(rp->value); } else emalloc(rp, struct redirect *, sizeof(struct redirect), "redirect"); - emalloc(str, char *, redir_exp->stlen + 1, "redirect"); - memcpy(str, redir_exp->stptr, redir_exp->stlen); - str[redir_exp->stlen] = '\0'; + emalloc(newstr, char *, explen + 1, "redirect"); + memcpy(newstr, str, explen); + newstr[explen] = '\0'; + str = newstr; rp->value = str; rp->flag = tflag; init_output_wrapper(& rp->output); @@ -998,6 +997,15 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) return rp; } +struct redirect * +redirect(NODE *redir_exp, int redirtype, int *errflg) +{ + int not_string = ((redir_exp->flags & STRCUR) == 0); + redir_exp = force_string(redir_exp); + return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string, + redirtype, errflg); +} + /* getredirect --- find the struct redirect for this file or pipe */ struct redirect * -- cgit v1.2.3 From 1f647aac9fa3e412c63a966535de8ee4fec855f2 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Tue, 2 Jul 2013 12:20:56 -0400 Subject: Enhance getline to return -2 when an I/O operation should be retried. --- io.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 14b8df91..0ba36451 100644 --- a/io.c +++ b/io.c @@ -555,7 +555,7 @@ inrec(IOBUF *iop, int *errcode) else cnt = get_a_record(& begin, iop, errcode); - if (cnt == EOF) { + if (cnt < 0) { retval = 1; if (*errcode > 0) update_ERRNO_int(*errcode); @@ -2210,12 +2210,13 @@ wait_any(int interesting) /* pid of interest, if any */ if (pid == redp->pid) { redp->pid = -1; redp->status = status; - break; + goto finished; } } if (pid == -1 && errno == ECHILD) break; } +finished: signal(SIGHUP, hstat); signal(SIGQUIT, qstat); #endif @@ -2439,7 +2440,7 @@ do_getline_redir(int into_variable, enum redirval redirtype) if (errcode != 0) { if (! do_traditional && (errcode != -1)) update_ERRNO_int(errcode); - return make_number((AWKNUM) -1.0); + return make_number((AWKNUM) cnt); } if (cnt == EOF) { @@ -2489,7 +2490,7 @@ do_getline(int into_variable, IOBUF *iop) update_ERRNO_int(errcode); if (into_variable) (void) POP_ADDRESS(); - return make_number((AWKNUM) -1.0); + return make_number((AWKNUM) cnt); } if (cnt == EOF) @@ -3427,6 +3428,32 @@ find_longest_terminator: return REC_OK; } +/* Does the I/O error indicate that the operation should be retried later? */ + +static inline int +errno_io_retry(void) +{ + switch (errno) { +#ifdef EAGAIN + case EAGAIN: +#endif +#ifdef EWOULDBLOCK +#if !defined(EAGAIN) || (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif +#endif +#ifdef EINTR + case EINTR: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif + return 1; + default: + return 0; + } +} + /* * get_a_record --- read a record from IOP into out, * return length of EOF, set RT. @@ -3474,8 +3501,10 @@ get_a_record(char **out, /* pointer to pointer to data */ iop->flag |= IOP_AT_EOF; return EOF; } else if (iop->count == -1) { - iop->flag |= IOP_AT_EOF; *errcode = errno; + if (errno_io_retry()) + return -2; + iop->flag |= IOP_AT_EOF; return EOF; } else { iop->dataend = iop->buf + iop->count; @@ -3540,6 +3569,8 @@ get_a_record(char **out, /* pointer to pointer to data */ iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read); if (iop->count == -1) { *errcode = errno; + if (errno_io_retry()) + return -2; iop->flag |= IOP_AT_EOF; break; } else if (iop->count == 0) { -- cgit v1.2.3 From ad5c8d1f818c96579fa9e7f3c691739e9761e1e7 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 4 Jul 2013 16:26:51 -0400 Subject: Revert incorrect patch to wait_any and instead use waitpid to avoid blocking. --- io.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 0ba36451..42c92e47 100644 --- a/io.c +++ b/io.c @@ -2168,7 +2168,16 @@ use_pipes: #ifndef PIPES_SIMULATED /* real pipes */ -/* wait_any --- wait for a child process, close associated pipe */ +/* + * wait_any --- if the argument pid is 0, wait for all child processes that + * have exited. We loop to make sure to reap all children that have exited to + * minimize the risk of running out of process slots. Since we don't process + * SIGCHLD, we do not immediately reap exited children. So when we get here, + * we want to reap any that have piled up. + * + * Note: on platforms that do not support waitpid with WNOHANG, when called with + * a zero argument, this function will hang until all children have exited. + */ static int wait_any(int interesting) /* pid of interest, if any */ @@ -2198,7 +2207,11 @@ wait_any(int interesting) /* pid of interest, if any */ hstat = signal(SIGHUP, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); for (;;) { -# ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */ +# if defined(HAVE_WAITPID) && defined(WNOHANG) + if ((pid = waitpid(-1, & status, WNOHANG)) == 0) + /* No children have exited */ + break; +# elif defined(HAVE_SYS_WAIT_H) /* POSIX compatible sys/wait.h */ pid = wait(& status); # else pid = wait((union wait *) & status); @@ -2210,13 +2223,12 @@ wait_any(int interesting) /* pid of interest, if any */ if (pid == redp->pid) { redp->pid = -1; redp->status = status; - goto finished; + break; } } if (pid == -1 && errno == ECHILD) break; } -finished: signal(SIGHUP, hstat); signal(SIGQUIT, qstat); #endif -- cgit v1.2.3 From faf3affc19f760a330153b22a8e56fc9a13a0cb6 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 7 Jul 2013 12:57:40 -0400 Subject: In io.c:wait_any, use sigprocmask if available. --- io.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index 42c92e47..01dc7cbe 100644 --- a/io.c +++ b/io.c @@ -2177,17 +2177,34 @@ use_pipes: * * Note: on platforms that do not support waitpid with WNOHANG, when called with * a zero argument, this function will hang until all children have exited. + * + * AJS, 2013-07-07: I do not see why we need to ignore signals during this + * function. This function just waits and updates the pid and status fields. + * I don't see why that should interfere with any signal handlers. But I am + * reluctant to remove this protection. So I changed to use sigprocmask to + * block signals instead to avoid interfering with installed signal handlers. */ static int wait_any(int interesting) /* pid of interest, if any */ { - RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int); int pid; int status = 0; struct redirect *redp; +#ifdef HAVE_SIGPROCMASK + sigset_t set, oldset; + + /* I have no idea why we are blocking signals during this function... */ + sigemptyset(& set); + sigaddset(& set, SIGINT); + sigaddset(& set, SIGHUP); + sigaddset(& set, SIGQUIT); + sigprocmask(SIG_BLOCK, & set, & oldset); +#else + RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int); istat = signal(SIGINT, SIG_IGN); +#endif #ifdef __MINGW32__ if (interesting < 0) { status = -1; @@ -2204,8 +2221,10 @@ wait_any(int interesting) /* pid of interest, if any */ } } #else +#ifndef HAVE_SIGPROCMASK hstat = signal(SIGHUP, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); +#endif for (;;) { # if defined(HAVE_WAITPID) && defined(WNOHANG) if ((pid = waitpid(-1, & status, WNOHANG)) == 0) @@ -2229,10 +2248,16 @@ wait_any(int interesting) /* pid of interest, if any */ if (pid == -1 && errno == ECHILD) break; } +#ifndef HAVE_SIGPROCMASK signal(SIGHUP, hstat); signal(SIGQUIT, qstat); #endif +#endif +#ifndef HAVE_SIGPROCMASK signal(SIGINT, istat); +#else + sigprocmask(SIG_SETMASK, & oldset, NULL); +#endif return status; } -- cgit v1.2.3 From 74ee0dcab17240a1626b77ed998b07f0f6560a48 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 15 Oct 2014 11:40:12 +0300 Subject: Sanitize handling of AWKPATH / AWKLIBPATH. --- io.c | 45 --------------------------------------------- 1 file changed, 45 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 7154a710..32caadfb 100644 --- a/io.c +++ b/io.c @@ -2505,7 +2505,6 @@ do_getline(int into_variable, IOBUF *iop) typedef struct { const char *envname; char **dfltp; /* pointer to address of default path */ - char try_cwd; /* always search current directory? */ char **awkpath; /* array containing library search paths */ int max_pathlen; /* length of the longest item in awkpath */ } path_info; @@ -2513,13 +2512,11 @@ typedef struct { static path_info pi_awkpath = { /* envname */ "AWKPATH", /* dfltp */ & defpath, - /* try_cwd */ true, }; static path_info pi_awklibpath = { /* envname */ "AWKLIBPATH", /* dfltp */ & deflibpath, - /* try_cwd */ false, }; /* init_awkpath --- split path(=$AWKPATH) into components */ @@ -2577,30 +2574,6 @@ init_awkpath(path_info *pi) #undef INC_PATH } -/* get_cwd -- get current working directory */ - -static char * -get_cwd () -{ -#define BSIZE 100 - char *buf; - size_t bsize = BSIZE; - - emalloc(buf, char *, bsize * sizeof(char), "get_cwd"); - while (true) { - if (getcwd(buf, bsize) == buf) - return buf; - if (errno != ERANGE) { - efree(buf); - return NULL; - } - bsize *= 2; - erealloc(buf, char *, bsize * sizeof(char), "get_cwd"); - } -#undef BSIZE -} - - /* do_find_source --- search $AWKPATH for file, return NULL if not found */ static char * @@ -2622,24 +2595,6 @@ do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi) return NULL; } - /* try current directory before $AWKPATH search */ - if (pi->try_cwd && stat(src, stb) == 0) { - path = get_cwd(); - if (path == NULL) { - *errcode = errno; - return NULL; - } - erealloc(path, char *, strlen(path) + strlen(src) + 2, "do_find_source"); -#ifdef VMS - if (strcspn(path,">]:") == strlen(path)) - strcat(path, "/"); -#else - strcat(path, "/"); -#endif - strcat(path, src); - return path; - } - if (pi->awkpath == NULL) init_awkpath(pi); -- cgit v1.2.3 From c483c50817e8accd0d5052d41d00869330193175 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Wed, 5 Nov 2014 12:29:58 -0500 Subject: If getline fails due to a retryable I/O error, return -2 without closing the file only if PROCINFO[, "RETRY"] is configured. --- io.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 5692a519..6d816da7 100644 --- a/io.c +++ b/io.c @@ -3425,6 +3425,13 @@ find_longest_terminator: return REC_OK; } +/* return true if PROCINFO[, "RETRY"] exists */ +static inline int +retryable(IOBUF *iop) +{ + return PROCINFO_node && in_PROCINFO(iop->public.name, "RETRY", NULL); +} + /* Does the I/O error indicate that the operation should be retried later? */ static inline int @@ -3500,7 +3507,7 @@ get_a_record(char **out, /* pointer to pointer to data */ return EOF; } else if (iop->count == -1) { *errcode = errno; - if (errno_io_retry()) + if (errno_io_retry() && retryable(iop)) return -2; iop->flag |= IOP_AT_EOF; return EOF; @@ -3576,7 +3583,7 @@ get_a_record(char **out, /* pointer to pointer to data */ iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read); if (iop->count == -1) { *errcode = errno; - if (errno_io_retry()) + if (errno_io_retry() && retryable(iop)) return -2; iop->flag |= IOP_AT_EOF; break; -- cgit v1.2.3 From e3f20c041c078eacf648af94d9f012e4906359bb Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 6 Nov 2014 14:18:37 -0500 Subject: Enhance get_file API to return info about input and output and to enable extensions to create already-opened files or sockets. --- io.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 6d816da7..e9947da3 100644 --- a/io.c +++ b/io.c @@ -264,7 +264,7 @@ static IOBUF *iop_alloc(int fd, const char *name, int errno_val); static IOBUF *iop_finish(IOBUF *iop); static int gawk_pclose(struct redirect *rp); static int str2mode(const char *mode); -static int two_way_open(const char *str, struct redirect *rp); +static int two_way_open(const char *str, struct redirect *rp, int extfd); static int pty_vs_pipe(const char *command); static void find_input_parser(IOBUF *iop); static bool find_output_wrapper(awk_output_buf_t *outbuf); @@ -720,7 +720,7 @@ redflags2str(int flags) /* redirect --- Redirection for printf and print commands */ struct redirect * -redirect_string(char *str, size_t explen, int not_string, int redirtype, int *errflg) +redirect_string(const char *str, size_t explen, int not_string, int redirtype, int *errflg, int extfd) { struct redirect *rp; int tflag = 0; @@ -848,7 +848,7 @@ redirect_string(char *str, size_t explen, int not_string, int redirtype, int *er memcpy(newstr, str, explen); newstr[explen] = '\0'; str = newstr; - rp->value = str; + rp->value = newstr; rp->flag = tflag; init_output_wrapper(& rp->output); rp->output.name = str; @@ -880,6 +880,10 @@ redirect_string(char *str, size_t explen, int not_string, int redirtype, int *er mode = binmode("a"); break; case redirect_pipe: + if (extfd >= 0) { + warning(_("get_file cannot create pipe `%s' with fd %d"), str, extfd); + return NULL; + } /* synchronize output before new pipe */ (void) flush_io(); @@ -893,6 +897,10 @@ redirect_string(char *str, size_t explen, int not_string, int redirtype, int *er rp->flag |= RED_NOBUF; break; case redirect_pipein: + if (extfd >= 0) { + warning(_("get_file cannot create pipe `%s' with fd %d"), str, extfd); + return NULL; + } direction = "from"; if (gawk_popen(str, rp) == NULL) fatal(_("can't open pipe `%s' for input (%s)"), @@ -900,7 +908,7 @@ redirect_string(char *str, size_t explen, int not_string, int redirtype, int *er break; case redirect_input: direction = "from"; - fd = devopen(str, binmode("r")); + fd = (extfd >= 0) ? extfd : devopen(str, binmode("r")); if (fd == INVALID_HANDLE && errno == EISDIR) { *errflg = EISDIR; /* do not free rp, saving it for reuse (save_rp = rp) */ @@ -917,8 +925,14 @@ redirect_string(char *str, size_t explen, int not_string, int redirtype, int *er } break; case redirect_twoway: +#ifndef HAVE_SOCKETS + if (extfd >= 0) { + warning(_("get_file socket creation not supported on this platform for `%s' with fd %d"), str, extfd); + return NULL; + } +#endif direction = "to/from"; - if (! two_way_open(str, rp)) { + if (! two_way_open(str, rp, extfd)) { #ifdef HAVE_SOCKETS if (inetfile(str, NULL)) { *errflg = errno; @@ -937,7 +951,7 @@ redirect_string(char *str, size_t explen, int not_string, int redirtype, int *er if (mode != NULL) { errno = 0; rp->output.mode = mode; - fd = devopen(str, mode); + fd = (extfd >= 0) ? extfd : devopen(str, mode); if (fd > INVALID_HANDLE) { if (fd == fileno(stdin)) @@ -1042,7 +1056,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) int not_string = ((redir_exp->flags & STRCUR) == 0); redir_exp = force_string(redir_exp); return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string, - redirtype, errflg); + redirtype, errflg, -1); } /* getredirect --- find the struct redirect for this file or pipe */ @@ -1700,16 +1714,16 @@ strictopen: /* two_way_open --- open a two way communications channel */ static int -two_way_open(const char *str, struct redirect *rp) +two_way_open(const char *str, struct redirect *rp, int extfd) { static bool no_ptys = false; #ifdef HAVE_SOCKETS /* case 1: socket */ - if (inetfile(str, NULL)) { + if (extfd >= 0 || inetfile(str, NULL)) { int fd, newfd; - fd = devopen(str, "rw"); + fd = (extfd >= 0) ? extfd : devopen(str, "rw"); if (fd == INVALID_HANDLE) return false; if ((BINMODE & BINMODE_OUTPUT) != 0) -- cgit v1.2.3 From 0a050fa206e5d899f553b6ac492d389cb39591a2 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 12 Oct 2014 13:49:11 +0300 Subject: OS/2 fixes. --- io.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 32caadfb..c584a0c2 100644 --- a/io.c +++ b/io.c @@ -110,6 +110,14 @@ #ifdef __EMX__ #include + +#if !defined(_S_IFDIR) && defined(S_IFDIR) +#define _S_IFDIR S_IFDIR +#endif + +#if !defined(_S_IRWXU) && defined(S_IRWXU) +#define _S_IRWXU S_IRWXU +#endif #endif #ifndef ENFILE -- cgit v1.2.3 From 8b863f8852067b0638e09dc7c82355b96381dc12 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sat, 15 Nov 2014 18:35:45 +0200 Subject: Remove MBS_SUPPORT ifdefs. --- io.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index c584a0c2..1d15d887 100644 --- a/io.c +++ b/io.c @@ -3073,10 +3073,8 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) { char *bp; char rs; -#if MBS_SUPPORT size_t mbclen = 0; mbstate_t mbs; -#endif memset(recm, '\0', sizeof(struct recmatch)); rs = RS->stptr[0]; @@ -3087,7 +3085,6 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) if (*state == INDATA) /* skip over data we've already seen */ bp += iop->scanoff; -#if MBS_SUPPORT /* * From: Bruno Haible * To: Aharon Robbins , gnits@gnits.org @@ -3184,7 +3181,7 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) return NOTERM; } } -#endif + while (*bp != rs) bp++; -- cgit v1.2.3 From dcaab6dd8a28be8885ccc508c49b962a61ab09fe Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sat, 20 Dec 2014 19:56:44 +0200 Subject: Start at non-fatal output via PROCINFO. --- io.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'io.c') 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); -- cgit v1.2.3 From 15a1d8d213380bd99b5dfe7f4cafcd6dedb8f0dc Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sat, 27 Dec 2014 21:20:47 +0200 Subject: Make nonfatal work with stdout & stderr. Update doc more. --- io.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index b4688c89..b3819c01 100644 --- a/io.c +++ b/io.c @@ -1085,6 +1085,25 @@ getredirect(const char *str, int len) return NULL; } +/* is_non_fatal_std --- return true if fp is stdout/stderr and nonfatal */ + +bool +is_non_fatal_std(FILE *fp) +{ + if (in_PROCINFO("nonfatal", NULL, NULL)) + return true; + + /* yucky logic. sigh. */ + if (fp == stdout) { + return ( in_PROCINFO("-", "nonfatal", NULL) != NULL + || in_PROCINFO("/dev/stdout", "nonfatal", NULL) != NULL); + } else if (fp == stderr) { + return (in_PROCINFO("/dev/stderr", "nonfatal", NULL) != NULL); + } + + return false; +} + /* close_one --- temporarily close an open file to re-use the fd */ static void -- cgit v1.2.3 From 0d867aa42ea8c3487678dcceea484c10c88914cb Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Mon, 5 Jan 2015 12:37:43 -0500 Subject: Fix bug in io.c:wait_any where we may not have waited for the requested child process exit status. --- io.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index 6e6d1a1a..f849f839 100644 --- a/io.c +++ b/io.c @@ -2250,7 +2250,12 @@ wait_any(int interesting) /* pid of interest, if any */ #endif for (;;) { # if defined(HAVE_WAITPID) && defined(WNOHANG) - if ((pid = waitpid(-1, & status, WNOHANG)) == 0) + /* + * N.B. If the caller wants status for a specific child process + * (i.e. interesting is non-zero), then we must hang until we + * get exit status for that child. + */ + if ((pid = waitpid(-1, & status, (interesting ? 0 : WNOHANG))) == 0) /* No children have exited */ break; # elif defined(HAVE_SYS_WAIT_H) /* POSIX compatible sys/wait.h */ -- cgit v1.2.3 From 2f9c84e82632cbce017a6d342acb3dede5e59e12 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 8 Feb 2015 19:45:44 +0200 Subject: Reset non-fatal-io to 31 December, add fixes from Andrew Schorr. --- io.c | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index b3819c01..db8a0a2b 100644 --- a/io.c +++ b/io.c @@ -261,7 +261,6 @@ struct recmatch { static int iop_close(IOBUF *iop); -struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg); static void close_one(void); static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how); #ifndef PIPES_SIMULATED @@ -718,7 +717,6 @@ redflags2str(int flags) { RED_PTY, "RED_PTY" }, { RED_SOCKET, "RED_SOCKET" }, { RED_TCP, "RED_TCP" }, - { RED_NON_FATAL, "RED_NON_FATAL" }, { 0, NULL } }; @@ -728,7 +726,7 @@ redflags2str(int flags) /* redirect --- Redirection for printf and print commands */ struct redirect * -redirect(NODE *redir_exp, int redirtype, int *errflg) +redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) { struct redirect *rp; char *str; @@ -745,8 +743,6 @@ 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")); @@ -756,7 +752,6 @@ 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) @@ -765,7 +760,6 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) what = ">>"; break; case redirect_pipe: - is_output = true; tflag = (RED_PIPE|RED_WRITE); what = "|"; break; @@ -778,7 +772,6 @@ 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; @@ -800,14 +793,6 @@ 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 @@ -907,7 +892,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) os_restore_mode(fileno(stdin)); /* - * Don't check is_non_fatal; see input pipe below. + * Don't check failure_fatal; see input pipe below. * Note that the failure happens upon failure to fork, * using a non-existant program will still succeed the * popen(). @@ -947,17 +932,11 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) case redirect_twoway: direction = "to/from"; if (! two_way_open(str, rp)) { -#ifdef HAVE_SOCKETS - if (inetfile(str, NULL)) { - *errflg = errno; - /* do not free rp, saving it for reuse (save_rp = rp) */ - return NULL; - } else if (is_non_fatal) { + if (! failure_fatal || is_non_fatal_redirect(str)) { *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)"), str, strerror(errno)); } @@ -1038,7 +1017,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) */ if (errflg != NULL) *errflg = errno; - if (! is_non_fatal && + if (failure_fatal && ! is_non_fatal_redirect(str) && (redirtype == redirect_output || redirtype == redirect_append)) { /* multiple messages make life easier for translators */ @@ -1104,6 +1083,15 @@ is_non_fatal_std(FILE *fp) return false; } +/* is_non_fatal_redirect --- return true if redirected I/O should be nonfatal */ + +bool +is_non_fatal_redirect(const char *str) +{ + return in_PROCINFO("nonfatal", NULL, NULL) != NULL + || in_PROCINFO(str, "nonfatal", NULL) != NULL; +} + /* close_one --- temporarily close an open file to re-use the fd */ static void @@ -2467,7 +2455,7 @@ do_getline_redir(int into_variable, enum redirval redirtype) assert(redirtype != redirect_none); redir_exp = TOP(); - rp = redirect(redir_exp, redirtype, & redir_error); + rp = redirect(redir_exp, redirtype, & redir_error, false); DEREF(redir_exp); decr_sp(); if (rp == NULL) { -- cgit v1.2.3 From 7f9f66525d7d82816eba352efdf58497373a47bf Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 8 Feb 2015 20:01:32 +0200 Subject: Use "NONFATAL" for nonfatal I/O. --- io.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index db8a0a2b..f975353e 100644 --- a/io.c +++ b/io.c @@ -1069,15 +1069,17 @@ getredirect(const char *str, int len) bool is_non_fatal_std(FILE *fp) { - if (in_PROCINFO("nonfatal", NULL, NULL)) + static const char nonfatal[] = "NONFATAL"; + + if (in_PROCINFO(nonfatal, NULL, NULL)) return true; /* yucky logic. sigh. */ if (fp == stdout) { - return ( in_PROCINFO("-", "nonfatal", NULL) != NULL - || in_PROCINFO("/dev/stdout", "nonfatal", NULL) != NULL); + return ( in_PROCINFO("-", nonfatal, NULL) != NULL + || in_PROCINFO("/dev/stdout", nonfatal, NULL) != NULL); } else if (fp == stderr) { - return (in_PROCINFO("/dev/stderr", "nonfatal", NULL) != NULL); + return (in_PROCINFO("/dev/stderr", nonfatal, NULL) != NULL); } return false; @@ -1088,8 +1090,8 @@ is_non_fatal_std(FILE *fp) bool is_non_fatal_redirect(const char *str) { - return in_PROCINFO("nonfatal", NULL, NULL) != NULL - || in_PROCINFO(str, "nonfatal", NULL) != NULL; + return in_PROCINFO("NONFATAL", NULL, NULL) != NULL + || in_PROCINFO(str, "NONFATAL", NULL) != NULL; } /* close_one --- temporarily close an open file to re-use the fd */ -- cgit v1.2.3 From 1752d5ee472ce827ee66ea38c33085123575a033 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 27 Feb 2015 08:59:09 +0200 Subject: Make socket open not immediately fatal. --- io.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index f975353e..b00aa300 100644 --- a/io.c +++ b/io.c @@ -1466,7 +1466,7 @@ str2mode(const char *mode) static int socketopen(int family, int type, const char *localpname, - const char *remotepname, const char *remotehostname) + const char *remotepname, const char *remotehostname, bool *hard_error) { struct addrinfo *lres, *lres0; struct addrinfo lhints; @@ -1485,8 +1485,11 @@ socketopen(int family, int type, const char *localpname, lerror = getaddrinfo(NULL, localpname, & lhints, & lres); if (lerror) { - if (strcmp(localpname, "0") != 0) - fatal(_("local port %s invalid in `/inet'"), localpname); + if (strcmp(localpname, "0") != 0) { + warning(_("local port %s invalid in `/inet'"), localpname); + *hard_error = true; + return INVALID_HANDLE; + } lres0 = NULL; lres = & lhints; } else @@ -1504,7 +1507,9 @@ socketopen(int family, int type, const char *localpname, if (rerror) { if (lres0 != NULL) freeaddrinfo(lres0); - fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname); + warning(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname); + *hard_error = true; + return INVALID_HANDLE; } rres0 = rres; socket_fd = INVALID_HANDLE; @@ -1668,6 +1673,7 @@ devopen(const char *name, const char *mode) static bool first_time = true; unsigned long retries = 0; static long msleep = 1000; + bool hard_error = false; if (first_time) { char *cp, *end; @@ -1697,9 +1703,9 @@ devopen(const char *name, const char *mode) retries = def_retries; do { - openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, name+isi.remoteport.offset, name+isi.remotehost.offset); + openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, name+isi.remoteport.offset, name+isi.remotehost.offset, & hard_error); retries--; - } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0); + } while (openfd == INVALID_HANDLE && ! hard_error && retries > 0 && usleep(msleep) == 0); } /* restore original name string */ -- cgit v1.2.3 From 765d3a443f5121f148d47ec813069e1257212d5e Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 27 Feb 2015 09:06:01 +0200 Subject: For non-fatal sockets, get a better error message. --- io.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index b00aa300..af963a80 100644 --- a/io.c +++ b/io.c @@ -1618,6 +1618,7 @@ devopen(const char *name, const char *mode) char *ptr; int flag = 0; struct inet_socket_info isi; + int save_errno = 0; if (strcmp(name, "-") == 0) return fileno(stdin); @@ -1702,10 +1703,12 @@ devopen(const char *name, const char *mode) } retries = def_retries; + errno = 0; do { openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, name+isi.remoteport.offset, name+isi.remotehost.offset, & hard_error); retries--; } while (openfd == INVALID_HANDLE && ! hard_error && retries > 0 && usleep(msleep) == 0); + save_errno = errno; } /* restore original name string */ @@ -1717,8 +1720,11 @@ devopen(const char *name, const char *mode) } strictopen: - if (openfd == INVALID_HANDLE) + if (openfd == INVALID_HANDLE) { openfd = open(name, flag, 0666); + if (openfd == INVALID_HANDLE && save_errno) + errno = save_errno; + } #if defined(__EMX__) || defined(__MINGW32__) if (openfd == INVALID_HANDLE && errno == EACCES) { /* On OS/2 and Windows directory access via open() is -- cgit v1.2.3 From 9fa41fc2c183d5920d64e6f34f8a6bb325188443 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sat, 28 Feb 2015 15:26:40 -0500 Subject: Improve testing for nonfatal socket connection attempts. --- io.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index af963a80..162fb4e8 100644 --- a/io.c +++ b/io.c @@ -3704,8 +3704,10 @@ pty_vs_pipe(const char *command) #ifdef HAVE_TERMIOS_H NODE *val; - if (PROCINFO_node == NULL) - return false; + /* + * N.B. No need to check for NULL PROCINFO_node, since the + * in_PROCINFO function now checks that for us. + */ val = in_PROCINFO(command, "pty", NULL); if (val) { if ((val->flags & MAYBE_NUM) != 0) -- cgit v1.2.3 From b108a3ba2ab12dd7274589c6fe09c882df02827c Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 8 Mar 2015 06:06:19 +0200 Subject: Make nonfatal override GAWK_SOCK_RETRIES. Document it. --- io.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 162fb4e8..55c5d3a5 100644 --- a/io.c +++ b/io.c @@ -1661,20 +1661,20 @@ devopen(const char *name, const char *mode) goto strictopen; } else if (inetfile(name, & isi)) { #ifdef HAVE_SOCKETS - cp = (char *) name; - - /* socketopen requires NUL-terminated strings */ - cp[isi.localport.offset+isi.localport.len] = '\0'; - cp[isi.remotehost.offset+isi.remotehost.len] = '\0'; - /* remoteport comes last, so already NUL-terminated */ - - { #define DEFAULT_RETRIES 20 static unsigned long def_retries = DEFAULT_RETRIES; static bool first_time = true; unsigned long retries = 0; static long msleep = 1000; bool hard_error = false; + bool non_fatal = is_non_fatal_redirect(name); + + cp = (char *) name; + + /* socketopen requires NUL-terminated strings */ + cp[isi.localport.offset+isi.localport.len] = '\0'; + cp[isi.remotehost.offset+isi.remotehost.len] = '\0'; + /* remoteport comes last, so already NUL-terminated */ if (first_time) { char *cp, *end; @@ -1701,28 +1701,39 @@ devopen(const char *name, const char *mode) msleep *= 1000; } } - retries = def_retries; + /* + * PROCINFO["NONFATAL"] or PROCINFO[name, "NONFATAL"] overrrides + * GAWK_SOCK_RETRIES. The explicit code in the program carries + * a bigger stick than the environment variable does. + */ + retries = non_fatal ? 1 : def_retries; errno = 0; do { - openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, name+isi.remoteport.offset, name+isi.remotehost.offset, & hard_error); + openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, + name+isi.remoteport.offset, name+isi.remotehost.offset, + & hard_error); retries--; } while (openfd == INVALID_HANDLE && ! hard_error && retries > 0 && usleep(msleep) == 0); save_errno = errno; - } - /* restore original name string */ - cp[isi.localport.offset+isi.localport.len] = '/'; - cp[isi.remotehost.offset+isi.remotehost.len] = '/'; + /* restore original name string */ + cp[isi.localport.offset+isi.localport.len] = '/'; + cp[isi.remotehost.offset+isi.remotehost.len] = '/'; #else /* ! HAVE_SOCKETS */ - fatal(_("TCP/IP communications are not supported")); + fatal(_("TCP/IP communications are not supported")); #endif /* HAVE_SOCKETS */ } strictopen: if (openfd == INVALID_HANDLE) { openfd = open(name, flag, 0666); - if (openfd == INVALID_HANDLE && save_errno) + /* + * ENOENT means there is no such name in the filesystem. + * Therefore it's ok to propagate up the error from + * getaddrinfo() that's in save_errno. + */ + if (openfd == INVALID_HANDLE && errno == ENOENT && save_errno) errno = save_errno; } #if defined(__EMX__) || defined(__MINGW32__) -- cgit v1.2.3 From 6522e5b623e083565229dc742336219a0dda1344 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 24 Mar 2015 22:58:20 +0200 Subject: General cleanups prepatory to merging. --- io.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 5f977355..4dbe16fb 100644 --- a/io.c +++ b/io.c @@ -724,7 +724,7 @@ redflags2str(int flags) return genflags2str(flags, redtab); } -/* redirect --- Redirection for printf and print commands */ +/* redirect_string --- Redirection for printf and print commands, use string info */ struct redirect * redirect_string(const char *str, size_t explen, bool not_string, @@ -1065,6 +1065,8 @@ redirect_string(const char *str, size_t explen, bool not_string, return rp; } +/* redirect --- Redirection for printf and print commands */ + struct redirect * redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) { @@ -2303,7 +2305,7 @@ wait_any(int interesting) /* pid of interest, if any */ break; } } -#else +#else /* ! __MINGW32__ */ #ifndef HAVE_SIGPROCMASK hstat = signal(SIGHUP, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); @@ -2340,7 +2342,7 @@ wait_any(int interesting) /* pid of interest, if any */ signal(SIGHUP, hstat); signal(SIGQUIT, qstat); #endif -#endif +#endif /* ! __MINGW32__ */ #ifndef HAVE_SIGPROCMASK signal(SIGINT, istat); #else @@ -3509,14 +3511,15 @@ find_longest_terminator: return REC_OK; } -/* return true if PROCINFO[, "RETRY"] exists */ +/* retryable --- return true if PROCINFO[, "RETRY"] exists */ + static inline int retryable(IOBUF *iop) { return PROCINFO_node && in_PROCINFO(iop->public.name, "RETRY", NULL); } -/* Does the I/O error indicate that the operation should be retried later? */ +/* errno_io_retry --- Does the I/O error indicate that the operation should be retried later? */ static inline int errno_io_retry(void) -- cgit v1.2.3 From 9d43b510f74f63806279ce40f65245ea7e5b0d53 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 27 Mar 2015 06:32:13 +0300 Subject: Some more cleanups. Ready to merge! --- io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index 4dbe16fb..cf9dd943 100644 --- a/io.c +++ b/io.c @@ -1070,7 +1070,8 @@ redirect_string(const char *str, size_t explen, bool not_string, struct redirect * redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) { - int not_string = ((redir_exp->flags & STRCUR) == 0); + bool not_string = ((redir_exp->flags & STRCUR) == 0); + redir_exp = force_string(redir_exp); return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string, redirtype, errflg, -1, failure_fatal); -- cgit v1.2.3