aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'io.c')
-rw-r--r--io.c111
1 files changed, 74 insertions, 37 deletions
diff --git a/io.c b/io.c
index fff13883..b8bab6d5 100644
--- a/io.c
+++ b/io.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2004 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -122,7 +122,7 @@ typedef enum recvalues {
REC_OK, /* record and terminator found, recmatch struct filled in */
NOTERM, /* no terminator found, give me more input data */
TERMATEND, /* found terminator at end of buffer */
- TERMNEAREND, /* found terminator close to end of buffer, for RE might be bigger */
+ TERMNEAREND /* found terminator close to end of buffer, for RE might be bigger */
} RECVALUE;
/* Between calls to a scanning routine, the state is stored in */
/* an [[enum scanstate]] variable. Not all states apply to all */
@@ -134,7 +134,7 @@ typedef enum scanstate {
NOSTATE, /* scanning not started yet (all) */
INLEADER, /* skipping leading data (RS = "") */
INDATA, /* in body of record (all) */
- INTERM, /* scanning terminator (RS = "", RS = regexp) */
+ INTERM /* scanning terminator (RS = "", RS = regexp) */
} SCANSTATE;
/* When a record is seen ([[REC_OK]] or [[TERMATEND]]), the following */
/* structure is filled in. */
@@ -201,6 +201,8 @@ static jmp_buf filebuf; /* for do_nextfile() */
#if defined(MSDOS) || defined(OS2) || defined(WIN32) \
|| defined(__EMX__) || defined(__CYGWIN__)
+/* binmode --- convert BINMODE to string for fopen */
+
static const char *
binmode(const char *mode)
{
@@ -245,7 +247,7 @@ static IOBUF *
nextfile(int skipping)
{
static long i = 1;
- static int files = 0;
+ static int files = FALSE;
NODE *arg;
static IOBUF *curfile = NULL;
static IOBUF mybuf;
@@ -274,7 +276,7 @@ nextfile(int skipping)
ARGIND_node->var_value = make_number((AWKNUM) i);
}
if (! arg_assign(arg->stptr, FALSE)) {
- files++;
+ files = TRUE;
fname = arg->stptr;
curfile = iop_open(fname, binmode("r"), &mybuf);
if (curfile == NULL)
@@ -288,10 +290,11 @@ nextfile(int skipping)
break;
}
}
- if (files == 0) {
- files++;
+ if (files == FALSE) {
+ files = TRUE;
/* no args. -- use stdin */
/* FNR is init'ed to 0 */
+ unref(FILENAME_node->var_value);
FILENAME_node->var_value = make_string("-", 1);
fname = "-";
curfile = iop_open(fname, binmode("r"), &mybuf);
@@ -305,7 +308,7 @@ nextfile(int skipping)
fatal(_("cannot open file `%s' for reading (%s)"),
fname, strerror(errno));
/* NOTREACHED */
- return 0;
+ return (IOBUF *) 0;
}
/* set_FNR --- update internal FNR from awk variable */
@@ -555,6 +558,22 @@ redirect(NODE *tree, int *errflg)
#endif /* HAVE_SOCKETS */
for (rp = red_head; rp != NULL; rp = rp->next) {
+#ifndef PIPES_SIMULATED
+ /*
+ * This is an efficiency hack. We want to
+ * recover the process slot for dead children,
+ * if at all possible. Messing with signal() for
+ * SIGCLD leads to lots of headaches. However, if
+ * we've gotten EOF from a child input pipeline, it's
+ * good bet that the child has died. So recover it.
+ */
+ if ((rp->flag & RED_EOF) && tree->type == Node_redirect_pipein) {
+ if (rp->pid != -1)
+ wait_any(0);
+ }
+#endif /* PIPES_SIMULATED */
+
+ /* now check for a match */
if (strlen(rp->value) == tmp->stlen
&& STREQN(rp->value, str, tmp->stlen)
&& ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag
@@ -769,8 +788,12 @@ close_one()
for (rp = red_head; rp != NULL; rp = rp->next)
rplast = rp;
/* now work back up through the list */
- for (rp = rplast; rp != NULL; rp = rp->prev)
- if (rp->fp != NULL && (rp->flag & RED_FILE) != 0) {
+ for (rp = rplast; rp != NULL; rp = rp->prev) {
+ /* don't close standard files! */
+ if (rp->fp == NULL || rp->fp == stderr || rp->fp == stdout)
+ continue;
+
+ if ((rp->flag & RED_FILE) != 0) {
rp->flag |= RED_USED;
errno = 0;
if (/* do_lint && */ fclose(rp->fp) != 0)
@@ -779,6 +802,7 @@ close_one()
rp->fp = NULL;
break;
}
+ }
if (rp == NULL)
/* surely this is the only reason ??? */
fatal(_("too many pipes or input files open"));
@@ -846,22 +870,13 @@ do_close(NODE *tree)
return tmp;
}
-/* close_redir --- close an open file or pipe */
+/* close_rp --- separate function to just do closing */
static int
-close_redir(register struct redirect *rp, int exitwarn, two_way_close_type how)
+close_rp(struct redirect *rp, two_way_close_type how)
{
int status = 0;
- if (rp == NULL)
- return 0;
- if (rp->fp == stdout || rp->fp == stderr)
- return 0;
-
- if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL)
- lintwarn(_("close: redirection `%s' not opened with `|&', second argument ignored"),
- rp->value);
-
errno = 0;
if ((rp->flag & RED_TWOWAY) != 0) { /* two-way pipe */
/* write end: */
@@ -911,6 +926,27 @@ close_redir(register struct redirect *rp, int exitwarn, two_way_close_type how)
}
}
+ return status;
+}
+
+/* close_redir --- close an open file or pipe */
+
+static int
+close_redir(register struct redirect *rp, int exitwarn, two_way_close_type how)
+{
+ int status = 0;
+
+ if (rp == NULL)
+ return 0;
+ if (rp->fp == stdout || rp->fp == stderr)
+ goto checkwarn; /* bypass closing, remove from list */
+
+ if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL)
+ lintwarn(_("close: redirection `%s' not opened with `|&', second argument ignored"),
+ rp->value);
+
+ status = close_rp(rp, how);
+
/* SVR4 awk checks and warns about status of close */
if (status != 0) {
char *s = strerror(errno);
@@ -934,6 +970,7 @@ close_redir(register struct redirect *rp, int exitwarn, two_way_close_type how)
}
}
+checkwarn:
if (exitwarn) {
/*
* Don't use lintwarn() here. If lint warnings are fatal,
@@ -1230,7 +1267,7 @@ devopen(const char *name, const char *mode)
char *cp;
char *ptr;
int flag = 0;
- extern double strtod();
+ extern unsigned long strtoul P((const char *, char **endptr, int base));
flag = str2mode(mode);
@@ -1258,7 +1295,7 @@ devopen(const char *name, const char *mode)
openfd = fileno(stderr);
else if (STREQN(cp, "fd/", 3)) {
cp += 3;
- openfd = (int) strtod(cp, &ptr);
+ openfd = (int) strtoul(cp, &ptr, 10);
if (openfd <= INVALID_HANDLE || ptr == cp)
openfd = INVALID_HANDLE;
}
@@ -1474,7 +1511,7 @@ useropen(IOBUF *iop, const char *name ATTRIBUTE_UNUSED, const char *mode ATTRIBU
sprintf(tbuf, "%d %d %d %d", (int) getuid(), (int) geteuid(), (int) getgid(), (int) getegid());
cp = tbuf + strlen(tbuf);
-#if defined(NGROUPS_MAX) && NGROUPS_MAX > 0
+#if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
for (i = 0; i < ngroups; i++) {
*cp++ = ' ';
sprintf(cp, "%d", (int) groupset[i]);
@@ -1778,7 +1815,7 @@ two_way_open(const char *str, struct redirect *rp)
signal(SIGPIPE, SIG_DFL);
execl("/bin/sh", "sh", "-c", str, NULL);
- _exit(127);
+ _exit(errno == ENOENT ? 127 : 126);
case -1:
save_errno = errno;
@@ -2014,7 +2051,7 @@ wait_any(int interesting) /* pid of interest, if any */
signal(SIGHUP, hstat);
signal(SIGINT, istat);
signal(SIGQUIT, qstat);
- return(status);
+ return status;
}
/* gawk_popen --- open an IOBUF on a child process */
@@ -2088,7 +2125,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
if (rp->iop == NULL)
(void) close(p[0]);
- return (rp->iop);
+ return rp->iop;
}
/* gawk_pclose --- close an open child pipe */
@@ -2137,7 +2174,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
current = NULL;
}
rp->ifp = current;
- return (rp->iop);
+ return rp->iop;
}
/* gawk_pclose --- close an open child pipe */
@@ -2186,7 +2223,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
rp->iop = iop_alloc(current, name, NULL);
if (rp->iop == NULL)
(void) close(current);
- return (rp->iop);
+ return rp->iop;
}
/* gawk_pclose --- close an open child pipe */
@@ -2336,10 +2373,10 @@ do_pathopen(const char *file)
int len;
if (STREQ(file, "-"))
- return (0);
+ return 0;
if (do_traditional)
- return (devopen(file, "r"));
+ return devopen(file, "r");
if (first) {
first = FALSE;
@@ -2352,7 +2389,7 @@ do_pathopen(const char *file)
/* some kind of path name, no search */
if (ispath(file))
- return (devopen(file, "r"));
+ return devopen(file, "r");
/* no arbitrary limits: */
len = strlen(awkpath) + strlen(file) + 2;
@@ -2374,7 +2411,7 @@ do_pathopen(const char *file)
strcpy(trypath, file);
if ((fd = devopen(trypath, "r")) > INVALID_HANDLE) {
free(trypath);
- return (fd);
+ return fd;
}
/* no luck, keep going */
@@ -2388,7 +2425,7 @@ do_pathopen(const char *file)
* working directory in it. Therefore try to open the file in the
* current directory.
*/
- return (devopen(file, "r"));
+ return devopen(file, "r");
}
#ifdef TEST
@@ -2636,7 +2673,7 @@ again:
/* case 1, no match */
if (research(RSre, bp, 0, iop->dataend - bp, TRUE) == -1) {
/* set len, in case this all there is. */
- recm->len = iop->dataend - iop->off - 1;
+ recm->len = iop->dataend - iop->off;
return NOTERM;
}
@@ -3010,8 +3047,8 @@ set_RS()
} else if (RS->stlen > 1) {
static int warned = FALSE;
- RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, FALSE);
- RS_re_no_case = make_regexp(RS->stptr, RS->stlen, TRUE);
+ RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, FALSE, TRUE);
+ RS_re_no_case = make_regexp(RS->stptr, RS->stlen, TRUE, TRUE);
RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case);
matchrec = rsrescan;