aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-11-12 12:23:33 +0200
committerArnold D. Robbins <arnold@skeeve.com>2010-11-12 12:23:33 +0200
commit40b3741f63c19e38077d57f4ce4737916ec5073e (patch)
tree89e086fabdfc738b379901d86733e6c260c22f35 /io.c
parent00ef0423acd97cb964a2bae54c93a03a8ab50e5e (diff)
downloadegawk-40b3741f63c19e38077d57f4ce4737916ec5073e.tar.gz
egawk-40b3741f63c19e38077d57f4ce4737916ec5073e.tar.bz2
egawk-40b3741f63c19e38077d57f4ce4737916ec5073e.zip
Bring in development gawk changes.
Diffstat (limited to 'io.c')
-rw-r--r--io.c556
1 files changed, 236 insertions, 320 deletions
diff --git a/io.c b/io.c
index efeae9d4..852652ca 100644
--- a/io.c
+++ b/io.c
@@ -137,7 +137,6 @@ typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
#define at_eof(iop) ((iop->flag & IOP_AT_EOF) != 0)
#define has_no_data(iop) (iop->dataend == NULL)
#define no_data_left(iop) (iop->off >= iop->dataend)
-#define is_internal(iop) ((iop->flag & IOP_IS_INTERNAL) != 0)
/* The key point to the design is to split out the code that searches through */
/* a buffer looking for the record and the terminator into separate routines, */
/* with a higher-level routine doing the reading of data and buffer management. */
@@ -186,27 +185,21 @@ static int close_redir P((struct redirect *rp, int exitwarn, two_way_close_type
static int wait_any P((int interesting));
#endif
static IOBUF *gawk_popen P((const char *cmd, struct redirect *rp));
-static IOBUF *iop_open P((const char *file, const char *how, IOBUF *buf, int *isdir));
-static IOBUF *iop_alloc P((int fd, const char *name, IOBUF *buf));
+static IOBUF *iop_alloc P((int fd, const char *name, IOBUF *buf, int do_openhooks));
static int gawk_pclose P((struct redirect *rp));
static int do_pathopen P((const char *file));
static int str2mode P((const char *mode));
-static void spec_setup P((IOBUF *iop, int len));
-static IOBUF *specfdopen P((IOBUF *iop, const char *name, const char *mode));
-static IOBUF *pidopen P((IOBUF *iop, const char *name, const char *mode));
-static IOBUF *useropen P((IOBUF *iop, const char *name, const char *mode));
static int two_way_open P((const char *str, struct redirect *rp));
static int pty_vs_pipe P((const char *command));
+static void find_open_hook P((IOBUF *iop));
static RECVALUE rs1scan P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state));
static RECVALUE rsnullscan P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state));
static RECVALUE rsrescan P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state));
-
static RECVALUE (*matchrec) P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state)) = rs1scan;
-
static int get_a_record P((char **out, IOBUF *iop, int *errcode));
-
static void free_rp P((struct redirect *rp));
+static int inetfile P((const char *str, int *length, int *family));
#if defined(HAVE_POPEN_H)
#include "popen.h"
@@ -219,6 +212,8 @@ static Regexp *RS_re_no_case;
static Regexp *RS_regexp;
int RS_is_null;
+int in_beginfile_rule = FALSE; /* we're in a BEGINFILE rule */
+int in_endfile_rule = FALSE; /* we're in an ENDFILE rule */
extern int output_is_tty;
extern NODE *ARGC_node;
@@ -229,6 +224,12 @@ extern NODE **fields_arr;
static jmp_buf filebuf; /* for do_nextfile() */
+/* A block of AWK code to be run before each input file */
+NODE *beginfile_block = NULL;
+
+/* A block of AWK code to be run after each input file */
+NODE *endfile_block = NULL;
+
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__EMX__) || defined(__CYGWIN__)
/* binmode --- convert BINMODE to string for fopen */
@@ -261,13 +262,38 @@ static int vmsrtl_fileno(fp) FILE *fp; { return fileno(fp); }
#define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1)
#endif /* VMS */
+/* run_beginfile_rule --- run the BEGINFILE rule */
+
+static void
+run_beginfile_rule()
+{
+ if (beginfile_block != NULL) {
+ in_beginfile_rule = TRUE;
+ (void) interpret(beginfile_block);
+ }
+ in_beginfile_rule = FALSE;
+}
+
+/* run_endfile_rule --- run the ENDFILE rule */
+
+static void
+run_endfile_rule()
+{
+ if (endfile_block != NULL) {
+ in_endfile_rule = TRUE;
+ (void) interpret(endfile_block);
+ }
+ in_endfile_rule = FALSE;
+}
+
/* do_nextfile --- implement gawk "nextfile" extension */
void
do_nextfile()
{
(void) nextfile(TRUE);
- longjmp(filebuf, 1);
+ if (! in_beginfile_rule)
+ longjmp(filebuf, 1);
}
/* nextfile --- move to the next input data file */
@@ -281,17 +307,29 @@ nextfile(int skipping)
static IOBUF *curfile = NULL;
static IOBUF mybuf;
const char *fname;
+ int fd = INVALID_HANDLE;
+ static int called_recursively = FALSE;
+ int errcode;
+
+ if (in_beginfile_rule) {
+ called_recursively = TRUE;
+ return NULL;
+ }
if (skipping) {
if (curfile != NULL)
iop_close(curfile);
curfile = NULL;
+
+ run_endfile_rule();
return NULL;
}
if (curfile != NULL) {
if (at_eof(curfile)) {
(void) iop_close(curfile);
curfile = NULL;
+
+ run_endfile_rule();
} else
return curfile;
}
@@ -309,27 +347,50 @@ nextfile(int skipping)
files = TRUE;
fname = arg->stptr;
- curfile = iop_open(fname, binmode("r"), &mybuf, & isdir);
- if (curfile == NULL) {
-#if NO_DIRECTORY_FATAL
- if (isdir)
- continue;
-#else
- if (isdir && do_traditional)
+ errno = 0;
+ fd = devopen(fname, binmode("r"), & isdir);
+ errcode = errno;
+ if (isdir && errno == 0)
+ errcode = errno = EISDIR;
+ if (! do_traditional)
+ update_ERRNO();
+
+ /* This is a kludge. */
+ unref(FILENAME_node->var_value);
+ FILENAME_node->var_value = dupnode(arg);
+ FNR = 0;
+ /* Another kludge, so BEGINFILE can see FNR */
+ FNR_node->var_value->numbr = 0;
+
+ run_beginfile_rule();
+ if (called_recursively) {
+ called_recursively = FALSE;
+ if (curfile == NULL)
continue;
-#endif
- if (whiny_users) {
- warning(_("cannot open file `%s' for reading (%s)"),
- fname, strerror(errno));
+ }
+
+ if (fd == INVALID_HANDLE) {
+ if (isdir) {
+ if (do_traditional)
+ goto give_up;
+
+ errno = 0;
+ update_ERRNO();
+ warning(_("command line argument `%s' is a directory: skipped"), fname);
continue;
}
+ errno = errcode;
goto give_up;
}
+
+ /*
+ * Open hooks could have been changed by BEGINFILE,
+ * so delay check until now.
+ */
+ find_open_hook(curfile);
+
+ curfile = iop_alloc(fd, fname, &mybuf, FALSE);
curfile->flag |= IOP_NOFREE_OBJ;
- /* This is a kludge. */
- unref(FILENAME_node->var_value);
- FILENAME_node->var_value = dupnode(arg);
- FNR = 0;
i++;
break;
}
@@ -341,7 +402,7 @@ nextfile(int skipping)
unref(FILENAME_node->var_value);
FILENAME_node->var_value = make_string("-", 1);
fname = "-";
- curfile = iop_open(fname, binmode("r"), &mybuf, NULL);
+ curfile = iop_alloc(fileno(stdin), fname, &mybuf, TRUE);
if (curfile == NULL)
goto give_up;
curfile->flag |= IOP_NOFREE_OBJ;
@@ -352,7 +413,7 @@ give_up:
fatal(_("cannot open file `%s' for reading (%s)"),
fname, strerror(errno));
/* NOTREACHED */
- return (IOBUF *) 0;
+ return (IOBUF *) NULL;
}
/* set_FNR --- update internal FNR from awk variable */
@@ -379,17 +440,27 @@ inrec(IOBUF *iop)
char *begin;
register int cnt;
int retval = 0;
+ int errcode = 0;
+ extern NODE *endfile_block;
+
if (at_eof(iop) && no_data_left(iop))
cnt = EOF;
else if ((iop->flag & IOP_CLOSED) != 0)
cnt = EOF;
else
- cnt = get_a_record(&begin, iop, NULL);
+ cnt = get_a_record(&begin, iop, & errcode);
if (cnt == EOF) {
cnt = 0;
retval = 1;
+ if (errcode > 0) {
+ if (do_traditional || endfile_block == NULL)
+ fatal(_("error reading input file `%s': %s"),
+ iop->name, strerror(errcode));
+ else
+ update_ERRNO_saved(errcode);
+ }
} else {
NR += 1;
FNR += 1;
@@ -419,14 +490,6 @@ iop_close(IOBUF *iop)
ret = 0;
else
#endif
- /* save these for re-use; don't free the storage */
- if ((iop->flag & IOP_IS_INTERNAL) != 0) {
- iop->off = iop->buf;
- iop->end = iop->buf + strlen(iop->buf);
- iop->count = 0;
- return 0;
- }
-
/* Don't close standard files or else crufty code elsewhere will lose */
/* FIXME: *DO* close it. Just reopen on an invalid handle. */
if (iop->fd == fileno(stdin)
@@ -442,37 +505,35 @@ iop_close(IOBUF *iop)
if (ret == -1)
warning(_("close of fd %d (`%s') failed (%s)"), iop->fd,
iop->name, strerror(errno));
- if ((iop->flag & IOP_NO_FREE) == 0) {
- /*
- * Be careful -- $0 may still reference the buffer even though
- * an explicit close is being done; in the future, maybe we
- * can do this a bit better.
- */
- if (iop->buf) {
- if ((fields_arr[0]->stptr >= iop->buf)
- && (fields_arr[0]->stptr < (iop->buf + iop->size))) {
- NODE *t;
-
- t = make_string(fields_arr[0]->stptr,
- fields_arr[0]->stlen);
- unref(fields_arr[0]);
- fields_arr[0] = t;
- /*
- * 1/27/2003: This used to be here:
- *
- * reset_record();
- *
- * Don't do that; reset_record() throws away all fields,
- * saves FS etc. We just need to make sure memory isn't
- * corrupted and that references to $0 and fields work.
- */
- }
- free(iop->buf);
- iop->buf = NULL;
+ /*
+ * Be careful -- $0 may still reference the buffer even though
+ * an explicit close is being done; in the future, maybe we
+ * can do this a bit better.
+ */
+ if (iop->buf) {
+ if ((fields_arr[0]->stptr >= iop->buf)
+ && (fields_arr[0]->stptr < (iop->buf + iop->size))) {
+ NODE *t;
+
+ t = make_string(fields_arr[0]->stptr,
+ fields_arr[0]->stlen);
+ unref(fields_arr[0]);
+ fields_arr[0] = t;
+ /*
+ * 1/27/2003: This used to be here:
+ *
+ * reset_record();
+ *
+ * Don't do that; reset_record() throws away all fields,
+ * saves FS etc. We just need to make sure memory isn't
+ * corrupted and that references to $0 and fields work.
+ */
}
- if ((iop->flag & IOP_NOFREE_OBJ) == 0)
- free((char *) iop);
+ free(iop->buf);
+ iop->buf = NULL;
}
+ if ((iop->flag & IOP_NOFREE_OBJ) == 0)
+ free((char *) iop);
return ret == -1 ? 1 : 0;
}
@@ -550,6 +611,10 @@ redirect(NODE *tree, int *errflg)
const char *what = NULL;
int isdir = FALSE;
int new_rp = FALSE;
+ int len; /* used with /inet */
+
+ if (do_sandbox)
+ fatal(_("redirection not allowed in sandbox mode"));
switch (tree->type) {
case Node_redirect_append:
@@ -599,10 +664,14 @@ redirect(NODE *tree, int *errflg)
&& (STREQN(str, "0", tmp->stlen) || STREQN(str, "1", tmp->stlen)))
lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"), str, what);
+ /*
+ * XXX: Use /inet4 and /inet6 with plain /inet being whatever
+ * we get back from the system.
+ */
#ifdef HAVE_SOCKETS
- if (STREQN(str, "/inet/", 6)) {
+ if (inetfile(str, & len, NULL)) {
tflag |= RED_SOCKET;
- if (STREQN(str + 6, "tcp/", 4))
+ if (STREQN(str + len, "tcp/", 4))
tflag |= RED_TCP; /* use shutdown when closing */
}
#endif /* HAVE_SOCKETS */
@@ -696,7 +765,7 @@ redirect(NODE *tree, int *errflg)
break;
case Node_redirect_input:
direction = "from";
- rp->iop = iop_open(str, binmode("r"), NULL, & isdir);
+ rp->iop = iop_alloc(devopen(str, binmode("r"), & isdir), str, NULL, TRUE);
if (isdir) {
*errflg = EISDIR;
free_rp(rp);
@@ -707,7 +776,7 @@ redirect(NODE *tree, int *errflg)
direction = "to/from";
if (! two_way_open(str, rp)) {
#ifdef HAVE_SOCKETS
- if (STREQN(str, "/inet/", 6)) {
+ if (inetfile(str, NULL, NULL)) {
*errflg = errno;
free_temp(tmp);
free_rp(rp);
@@ -723,7 +792,7 @@ redirect(NODE *tree, int *errflg)
}
if (mode != NULL) {
errno = 0;
- fd = devopen(str, mode);
+ fd = devopen(str, mode, NULL);
if (fd > INVALID_HANDLE) {
if (fd == fileno(stdin))
rp->fp = stdin;
@@ -1198,8 +1267,8 @@ str2mode(const char *mode)
/* socketopen --- open a socket and set it into connected state */
static int
-socketopen(int type, const char *localpname, const char *remotepname,
- const char *remotehostname)
+socketopen(int family, int type, const char *localpname,
+ const char *remotepname, const char *remotehostname)
{
struct addrinfo *lres, *lres0;
struct addrinfo lhints;
@@ -1215,6 +1284,7 @@ socketopen(int type, const char *localpname, const char *remotepname,
memset (&lhints, '\0', sizeof (lhints));
lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
lhints.ai_socktype = type;
+ lhints.ai_family = family;
lerror = getaddrinfo (NULL, localpname, &lhints, &lres);
if (lerror) {
@@ -1335,24 +1405,19 @@ nextrres:
/* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
/*
- * This separate version is still needed for output, since file and pipe
- * output is done with stdio. iop_open() handles input with IOBUFs of
- * more "special" files. Those files are not handled here since it makes
- * no sense to use them for output.
- */
-
-/*
* Strictly speaking, "name" is not a "const char *" because we temporarily
* change the string.
*/
int
-devopen(const char *name, const char *mode)
+devopen(const char *name, const char *mode, int *isdir)
{
int openfd;
char *cp;
char *ptr;
int flag = 0;
+ int len;
+ int family;
extern unsigned long strtoul P((const char *, char **endptr, int base));
flag = str2mode(mode);
@@ -1380,15 +1445,18 @@ devopen(const char *name, const char *mode)
else if (STREQ(cp, "stderr") && (flag & O_ACCMODE) == O_WRONLY)
openfd = fileno(stderr);
else if (STREQN(cp, "fd/", 3)) {
+ struct stat sbuf;
+
cp += 3;
openfd = (int) strtoul(cp, &ptr, 10);
- if (openfd <= INVALID_HANDLE || ptr == cp)
+ if (openfd <= INVALID_HANDLE || ptr == cp
+ || fstat(openfd, &sbuf) < 0)
openfd = INVALID_HANDLE;
}
/* do not set close-on-exec for inherited fd's */
if (openfd != INVALID_HANDLE)
return openfd;
- } else if (STREQN(name, "/inet/", 6)) {
+ } else if (inetfile(name, & len, & family)) {
#ifdef HAVE_SOCKETS
/* /inet/protocol/localport/hostname/remoteport */
int protocol;
@@ -1397,7 +1465,7 @@ devopen(const char *name, const char *mode)
char *localpname;
char *localpnamelastcharp;
- cp = (char *) name + 6;
+ cp = (char *) name + len;
/* which protocol? */
if (STREQN(cp, "tcp/", 4))
protocol = SOCK_STREAM;
@@ -1491,7 +1559,7 @@ devopen(const char *name, const char *mode)
retries = def_retries;
do {
- openfd = socketopen(protocol, localpname, cp, hostname);
+ openfd = socketopen(family, protocol, localpname, cp, hostname);
retries--;
} while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0);
}
@@ -1507,205 +1575,23 @@ strictopen:
if (openfd == INVALID_HANDLE)
openfd = open(name, flag, 0666);
if (openfd != INVALID_HANDLE) {
- if (os_isdir(openfd))
- fatal(_("file `%s' is a directory"), name);
-
- os_close_on_exec(openfd, name, "file", "");
- }
- return openfd;
-}
-
-
-/* spec_setup --- setup an IOBUF for a special internal file */
-
-static void
-spec_setup(IOBUF *iop, int len)
-{
- char *cp;
-
- emalloc(cp, char *, len+2, "spec_setup");
- iop->buf = cp;
- iop->off = iop->buf;
- iop->count = 0;
- iop->size = len;
- iop->end = iop->buf + len;
- iop->dataend = iop->end;
- iop->fd = -1;
- iop->flag = IOP_IS_INTERNAL | IOP_AT_START | IOP_NO_FREE;
-}
-
-/* specfdopen --- open an fd special file */
-
-static IOBUF *
-specfdopen(IOBUF *iop, const char *name, const char *mode)
-{
- int fd;
- IOBUF *tp;
-
- fd = devopen(name, mode);
- if (fd == INVALID_HANDLE)
- return NULL;
- tp = iop_alloc(fd, name, iop);
- if (tp == NULL) {
- /* don't leak fd's */
- close(fd);
- return NULL;
- }
- return tp;
-}
-
-#ifdef GETPGRP_VOID
-#define getpgrp_arg() /* nothing */
-#else
-#define getpgrp_arg() getpid()
-#endif
-
-/* pidopen --- "open" /dev/pid, /dev/ppid, and /dev/pgrpid */
-
-static IOBUF *
-pidopen(IOBUF *iop, const char *name, const char *mode ATTRIBUTE_UNUSED)
-{
- char tbuf[BUFSIZ];
- int i;
- const char *cp = name + 5;
-
- warning(_("use `PROCINFO[\"%s\"]' instead of `%s'"), cp, name);
-
- if (iop == NULL) {
- iop = iop_alloc(INTERNAL_HANDLE, name, iop);
- if (iop == NULL)
- return NULL;
- }
-
- if (name[6] == 'g')
- sprintf(tbuf, "%d\n", (int) getpgrp(getpgrp_arg()));
- else if (name[6] == 'i')
- sprintf(tbuf, "%d\n", (int) getpid());
- else
- sprintf(tbuf, "%d\n", (int) getppid());
- i = strlen(tbuf);
- spec_setup(iop, i);
- strcpy(iop->buf, tbuf);
- return iop;
-}
-
-/* useropen --- "open" /dev/user */
-
-/*
- * /dev/user creates a record as follows:
- * $1 = getuid()
- * $2 = geteuid()
- * $3 = getgid()
- * $4 = getegid()
- * If multiple groups are supported, then $5 through $NF are the
- * supplementary group set.
- */
-
-static IOBUF *
-useropen(IOBUF *iop, const char *name ATTRIBUTE_UNUSED, const char *mode ATTRIBUTE_UNUSED)
-{
- char tbuf[BUFSIZ], *cp;
- int i;
-
- warning(_("use `PROCINFO[...]' instead of `/dev/user'"));
-
- if (iop == NULL) {
- iop = iop_alloc(INTERNAL_HANDLE, name, iop);
- if (iop == NULL)
- return NULL;
- }
-
- sprintf(tbuf, "%d %d %d %d", (int) getuid(), (int) geteuid(), (int) getgid(), (int) getegid());
-
- cp = tbuf + strlen(tbuf);
-#if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
- for (i = 0; i < ngroups; i++) {
- *cp++ = ' ';
- sprintf(cp, "%d", (int) groupset[i]);
- cp += strlen(cp);
- }
-#endif
- *cp++ = '\n';
- *cp++ = '\0';
-
- i = strlen(tbuf);
- spec_setup(iop, i);
- strcpy(iop->buf, tbuf);
- return iop;
-}
-
-/* iop_open --- handle special and regular files for input */
-
-static IOBUF *
-iop_open(const char *name, const char *mode, IOBUF *iop, int *isdir)
-{
- int openfd = INVALID_HANDLE;
- int flag = 0;
- static struct internal {
- const char *name;
- int compare;
- IOBUF *(*fp) P((IOBUF *, const char *, const char *));
- } table[] = {
- { "/dev/fd/", 8, specfdopen },
- { "/dev/stdin", 10, specfdopen },
- { "/dev/stdout", 11, specfdopen },
- { "/dev/stderr", 11, specfdopen },
- { "/inet/", 6, specfdopen },
- { "/dev/pid", 8, pidopen },
- { "/dev/ppid", 9, pidopen },
- { "/dev/pgrpid", 11, pidopen },
- { "/dev/user", 9, useropen },
- };
- int devcount = sizeof(table) / sizeof(table[0]);
-
- flag = str2mode(mode);
-
- if (STREQ(name, "-"))
- openfd = fileno(stdin);
- else if (do_traditional)
- goto strictopen;
- else if (STREQN(name, "/dev/", 5) || STREQN(name, "/inet/", 6)) {
- int i;
-
- for (i = 0; i < devcount; i++) {
- if (STREQN(name, table[i].name, table[i].compare)) {
- if ((iop = (*table[i].fp)(iop, name, mode)) != NULL)
- return iop;
- else {
- warning(_("could not open `%s', mode `%s'"),
- name, mode);
- return NULL;
- }
- }
- }
- /* not in table, fall through to regular code */
- }
-
-strictopen:
- if (openfd == INVALID_HANDLE)
- openfd = open(name, flag, 0666);
- if (openfd != INVALID_HANDLE) {
if (os_isdir(openfd)) {
if (isdir)
*isdir = TRUE;
(void) close(openfd); /* don't leak fds */
/* Set useful error number. */
errno = EISDIR;
- return NULL;
+ return INVALID_HANDLE;
}
+
+ if (openfd > fileno(stderr))
+ os_close_on_exec(openfd, name, "file", "");
}
/*
- * At this point, fd could still be INVALID_HANDLE.
- * We pass it to `iop_alloc' anyway, in case an open hook
- * can manage to open the file.
+ * XXX: FIXME: if fd is INVALID_HANDLE, see if an open hook
+ * can do something.
*/
- iop = iop_alloc(openfd, name, iop);
- if (iop != NULL) {
- if (iop->fd > fileno(stderr))
- os_close_on_exec(iop->fd, name, "file", "");
- } else if (openfd != INVALID_HANDLE) /* have an fd, but IOP is null */
- (void) close(openfd); /* avoid fd leak */
- return iop;
+ return openfd;
}
/* two_way_open --- open a two way communications channel */
@@ -1717,10 +1603,10 @@ two_way_open(const char *str, struct redirect *rp)
#ifdef HAVE_SOCKETS
/* case 1: socket */
- if (STREQN(str, "/inet/", 6)) {
+ if (inetfile(str, NULL, NULL)) {
int fd, newfd;
- fd = devopen(str, "rw");
+ fd = devopen(str, "rw", NULL);
if (fd == INVALID_HANDLE)
return FALSE;
rp->fp = fdopen(fd, "w");
@@ -1734,7 +1620,7 @@ two_way_open(const char *str, struct redirect *rp)
return FALSE;
}
os_close_on_exec(newfd, str, "socket", "to/from");
- rp->iop = iop_alloc(newfd, str, NULL);
+ rp->iop = iop_alloc(newfd, str, NULL, TRUE);
if (rp->iop == NULL) {
fclose(rp->fp);
return FALSE;
@@ -1763,7 +1649,7 @@ two_way_open(const char *str, struct redirect *rp)
return FALSE;
}
os_close_on_exec(newfd, str, "portal", "to/from");
- rp->iop = iop_alloc(newfd, str, NULL);
+ rp->iop = iop_alloc(newfd, str, NULL, TRUE);
if (rp->iop == NULL) {
fclose(rp->fp);
return FALSE;
@@ -1954,7 +1840,7 @@ two_way_open(const char *str, struct redirect *rp)
fatal(_("close of slave pty failed (%s)"), strerror(errno));
rp->pid = pid;
- rp->iop = iop_alloc(master, str, NULL);
+ rp->iop = iop_alloc(master, str, NULL, TRUE);
if (rp->iop == NULL) {
(void) close(master);
(void) kill(pid, SIGKILL); /* overkill? (pardon pun) */
@@ -2094,7 +1980,7 @@ use_pipes:
/* parent */
rp->pid = pid;
- rp->iop = iop_alloc(ctop[0], str, NULL);
+ rp->iop = iop_alloc(ctop[0], str, NULL, TRUE);
if (rp->iop == NULL) {
(void) close(ctop[0]);
(void) close(ctop[1]);
@@ -2153,7 +2039,7 @@ wait_any(int interesting) /* pid of interest, if any */
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
for (;;) {
-#ifdef HAVE_SYS_WAIT_H /* Posix compatible sys/wait.h */
+#ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */
pid = wait(&status);
#else
pid = wait((union wait *)&status);
@@ -2244,7 +2130,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
fatal(_("close of pipe failed (%s)"), strerror(errno));
#endif
os_close_on_exec(p[0], cmd, "pipe", "from");
- rp->iop = iop_alloc(p[0], cmd, NULL);
+ rp->iop = iop_alloc(p[0], cmd, NULL, TRUE);
if (rp->iop == NULL)
(void) close(p[0]);
@@ -2291,7 +2177,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
if (current == NULL)
return NULL;
os_close_on_exec(fileno(current), cmd, "pipe", "from");
- rp->iop = iop_alloc(fileno(current), cmd, NULL);
+ rp->iop = iop_alloc(fileno(current), cmd, NULL, TRUE);
if (rp->iop == NULL) {
(void) pclose(current);
current = NULL;
@@ -2343,7 +2229,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
emalloc(pipes[current].command, char *, strlen(cmd)+1, "gawk_popen");
strcpy(pipes[current].command, cmd);
os_close_on_exec(current, cmd, "pipe", "from");
- rp->iop = iop_alloc(current, name, NULL);
+ rp->iop = iop_alloc(current, name, NULL, TRUE);
if (rp->iop == NULL)
(void) close(current);
return rp->iop;
@@ -2499,7 +2385,7 @@ do_pathopen(const char *file)
return 0;
if (do_traditional)
- return devopen(file, "r");
+ return devopen(file, "r", NULL);
if (first) {
first = FALSE;
@@ -2512,7 +2398,7 @@ do_pathopen(const char *file)
/* some kind of path name, no search */
if (ispath(file))
- return devopen(file, "r");
+ return devopen(file, "r", NULL);
/* no arbitrary limits: */
len = strlen(awkpath) + strlen(file) + 2;
@@ -2532,7 +2418,7 @@ do_pathopen(const char *file)
strcpy(cp, file);
} else
strcpy(trypath, file);
- if ((fd = devopen(trypath, "r")) > INVALID_HANDLE) {
+ if ((fd = devopen(trypath, "r", NULL)) > INVALID_HANDLE) {
free(trypath);
return fd;
}
@@ -2548,7 +2434,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", NULL);
}
#ifdef TEST
@@ -2582,15 +2468,28 @@ register_open_hook(void *(*open_func)(IOBUF *))
open_hooks = oh;
}
+/* find_open_hook --- search the list of open hooks */
+
+static void
+find_open_hook(IOBUF *iop)
+{
+ struct open_hook *oh;
+
+ /* walk through open hooks, stop at first one that responds */
+ for (oh = open_hooks; oh != NULL; oh = oh->next) {
+ if ((iop->opaque = (*oh->open_func)(iop)) != NULL)
+ break;
+ }
+}
+
/* iop_alloc --- allocate an IOBUF structure for an open fd */
static IOBUF *
-iop_alloc(int fd, const char *name, IOBUF *iop)
+iop_alloc(int fd, const char *name, IOBUF *iop, int do_openhooks)
{
struct stat sbuf;
- struct open_hook *oh;
int iop_malloced = FALSE;
-
+
if (iop == NULL) {
emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
iop_malloced = TRUE;
@@ -2600,11 +2499,8 @@ iop_alloc(int fd, const char *name, IOBUF *iop)
iop->fd = fd;
iop->name = name;
- /* walk through open hooks, stop at first one that responds */
- for (oh = open_hooks; oh != NULL; oh = oh->next) {
- if ((iop->opaque = (*oh->open_func)(iop)) != NULL)
- break;
- }
+ if (do_openhooks)
+ find_open_hook(iop);
if (iop->fd == INTERNAL_HANDLE)
return iop;
@@ -2638,45 +2534,46 @@ iop_alloc(int fd, const char *name, IOBUF *iop)
(void)(! do_traditional && (unref(RT_node->var_value), \
RT_node->var_value = make_string(str, len)))
+
/* grow must increase size of buffer, set end, make sure off and dataend point at */
/* right spot. */
/* */
/* */
/* <growbuffer>= */
/* grow_iop_buffer --- grow the buffer */
-
+
static void
grow_iop_buffer(IOBUF *iop)
{
size_t valid = iop->dataend - iop->off;
size_t off = iop->off - iop->buf;
size_t newsize;
-
+
/*
* Lop off original extra two bytes, double the size,
* add them back.
*/
newsize = ((iop->size - 2) * 2) + 2;
-
+
/* Check for overflow */
if (newsize <= iop->size)
fatal(_("could not allocate more input memory"));
-
+
/* Make sure there's room for a disk block */
if (newsize - valid < iop->readsize)
newsize += iop->readsize + 2;
-
+
/* Check for overflow, again */
if (newsize <= iop->size)
fatal(_("could not allocate more input memory"));
-
+
iop->size = newsize;
erealloc(iop->buf, char *, iop->size, "grow_iop_buffer");
iop->off = iop->buf + off;
iop->dataend = iop->off + valid;
iop->end = iop->buf + iop->size;
}
-
+
/* Here are the routines. */
/* */
/* */
@@ -3022,22 +2919,15 @@ get_a_record(char **out, /* pointer to pointer to data */
/* <fill initial buffer>= */
if (has_no_data(iop) || no_data_left(iop)) {
- if (is_internal(iop)) {
- iop->flag |= IOP_AT_EOF;
- return EOF;
- }
iop->count = read(iop->fd, iop->buf, iop->readsize);
if (iop->count == 0) {
iop->flag |= IOP_AT_EOF;
return EOF;
} else if (iop->count == -1) {
- if (! do_traditional && errcode != NULL) {
+ iop->flag |= IOP_AT_EOF;
+ if (errcode != NULL)
*errcode = errno;
- iop->flag |= IOP_AT_EOF;
- return EOF;
- } else
- fatal(_("error reading input file `%s': %s"),
- iop->name, strerror(errno));
+ return EOF;
} else {
iop->dataend = iop->buf + iop->count;
iop->off = iop->buf;
@@ -3071,10 +2961,7 @@ get_a_record(char **out, /* pointer to pointer to data */
recm.rt_start = iop->off + recm.len;
/* <read more data, break if EOF>= */
- if ((iop->flag & IOP_IS_INTERNAL) != 0) {
- iop->flag |= IOP_AT_EOF;
- break;
- } else {
+ {
#define min(x, y) (x < y ? x : y)
/* subtract one in read count to leave room for sentinel */
size_t room_left = iop->end - iop->dataend - 1;
@@ -3189,6 +3076,7 @@ get_a_record(char **out, /* pointer to pointer to data */
return retval;
}
+
/* set_RS --- update things as appropriate when RS is set */
@@ -3240,7 +3128,7 @@ set_RS()
} else
matchrec = rs1scan;
set_FS:
- if (! using_fieldwidths())
+ if (current_field_sep() == Using_FS)
set_FS();
}
@@ -3294,8 +3182,6 @@ iopflags2str(int flag)
{
static const struct flagtab values[] = {
{ IOP_IS_TTY, "IOP_IS_TTY" },
- { IOP_IS_INTERNAL, "IOP_IS_INTERNAL" },
- { IOP_NO_FREE, "IOP_NO_FREE" },
{ IOP_NOFREE_OBJ, "IOP_NOFREE_OBJ" },
{ IOP_AT_EOF, "IOP_AT_EOF" },
{ IOP_CLOSED, "IOP_CLOSED" },
@@ -3314,3 +3200,33 @@ free_rp(struct redirect *rp)
free(rp->value);
free(rp);
}
+
+/* is_inet --- return true for a /inet special file, set other values */
+
+static int
+inetfile(const char *str, int *length, int *family)
+{
+ int ret = FALSE;
+
+ if (STREQN(str, "/inet/", 6)) {
+ ret = TRUE;
+ if (length != NULL)
+ *length = 6;
+ if (family != NULL)
+ *family = AF_UNSPEC;
+ } else if (STREQN(str, "/inet4/", 7)) {
+ ret = TRUE;
+ if (length != NULL)
+ *length = 7;
+ if (family != NULL)
+ *family = AF_INET;
+ } else if (STREQN(str, "/inet6/", 7)) {
+ ret = TRUE;
+ if (length != NULL)
+ *length = 7;
+ if (family != NULL)
+ *family = AF_INET6;
+ }
+
+ return ret;
+}