2 * io.c --- routines for dealing with input and output and records
6 * Copyright (C) 1986, 1988, 1989, 1991-2011 the Free Software Foundation, Inc.
8 * This file is part of GAWK, the GNU implementation of the
9 * AWK Programming Language.
11 * GAWK is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * GAWK is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 /* For OSF/1 to get struct sockaddr_storage */
27 #if defined(__osf__) && !defined(_OSF_SOURCE)
33 #ifdef HAVE_SYS_PARAM_H
34 #undef RE_DUP_MAX /* avoid spurious conflict w/regex.h */
35 #include <sys/param.h>
36 #endif /* HAVE_SYS_PARAM_H */
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.h>
39 #endif /* HAVE_SYS_IOCTL_H */
42 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
54 #ifdef HAVE_SYS_SOCKET_H
55 #include <sys/socket.h>
58 #endif /* HAVE_SYS_SOCKET_H */
60 #ifdef HAVE_NETINET_IN_H
61 #include <netinet/in.h>
63 #ifdef HAVE_ARPA_INET_H
64 #include <arpa/inet.h>
67 #else /* ! HAVE_NETINET_IN_H */
69 #endif /* HAVE_NETINET_IN_H */
73 #endif /* HAVE_NETDB_H */
75 #ifndef HAVE_GETADDRINFO
76 #include "missing_d/getaddrinfo.h"
79 #ifndef AI_ADDRCONFIG /* This is a recent symbol, not everyone has it */
80 #define AI_ADDRCONFIG 0
81 #endif /* AI_ADDRCONFIG */
83 #ifndef HAVE_SOCKADDR_STORAGE
84 #define sockaddr_storage sockaddr /* for older systems */
85 #endif /* HAVE_SOCKADDR_STORAGE */
87 #endif /* HAVE_SOCKETS */
108 #define ENFILE EMFILE
125 #endif /* HAVE_SOCKETS */
127 #if defined(GAWK_AIX)
128 #undef TANDEM /* AIX defines this in one of its header files */
131 #if defined(__DJGPP__) || defined(__MINGW32__)
132 #define PIPES_SIMULATED
135 typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
137 /* Several macros make the code a bit clearer: */
140 /* <defines and enums>= */
141 #define at_eof(iop) (((iop)->flag & IOP_AT_EOF) != 0)
142 #define has_no_data(iop) ((iop)->dataend == NULL)
143 #define no_data_left(iop) ((iop)->off >= (iop)->dataend)
144 /* The key point to the design is to split out the code that searches through */
145 /* a buffer looking for the record and the terminator into separate routines, */
146 /* with a higher-level routine doing the reading of data and buffer management. */
147 /* This makes the code easier to manage; the buffering code is the same independent */
148 /* of how we find a record. Communication is via the return value: */
151 /* <defines and enums>= */
152 typedef enum recvalues {
153 REC_OK, /* record and terminator found, recmatch struct filled in */
154 NOTERM, /* no terminator found, give me more input data */
155 TERMATEND, /* found terminator at end of buffer */
156 TERMNEAREND /* found terminator close to end of buffer, for RE might be bigger */
158 /* Between calls to a scanning routine, the state is stored in */
159 /* an [[enum scanstate]] variable. Not all states apply to all */
160 /* variants, but the higher code doesn't really care. */
163 /* <defines and enums>= */
164 typedef enum scanstate {
165 NOSTATE, /* scanning not started yet (all) */
166 INLEADER, /* skipping leading data (RS = "") */
167 INDATA, /* in body of record (all) */
168 INTERM /* scanning terminator (RS = "", RS = regexp) */
170 /* When a record is seen ([[REC_OK]] or [[TERMATEND]]), the following */
171 /* structure is filled in. */
176 char *start; /* record start */
177 size_t len; /* length of record */
178 char *rt_start; /* start of terminator */
179 size_t rt_len; /* length of terminator */
183 static int iop_close(IOBUF *iop);
184 struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg);
185 static void close_one(void);
186 static int close_redir(struct redirect *rp, int exitwarn, two_way_close_type how);
187 #ifndef PIPES_SIMULATED
188 static int wait_any(int interesting);
190 static IOBUF *gawk_popen(const char *cmd, struct redirect *rp);
191 static IOBUF *iop_alloc(int fd, const char *name, IOBUF *buf, int do_openhooks);
192 static int gawk_pclose(struct redirect *rp);
193 static int str2mode(const char *mode);
194 static int two_way_open(const char *str, struct redirect *rp);
195 static int pty_vs_pipe(const char *command);
196 static void find_open_hook(IOBUF *iop);
198 static RECVALUE rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
199 static RECVALUE rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
200 static RECVALUE rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
202 static RECVALUE (*matchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = rs1scan;
204 static int get_a_record(char **out, IOBUF *iop, int *errcode);
206 static void free_rp(struct redirect *rp);
207 static int inetfile(const char *str, int *length, int *family);
209 #if defined(HAVE_POPEN_H)
213 static struct redirect *red_head = NULL;
215 static Regexp *RS_re_yes_case;
216 static Regexp *RS_re_no_case;
217 static Regexp *RS_regexp;
221 extern int output_is_tty;
222 extern NODE *ARGC_node;
223 extern NODE *ARGV_node;
224 extern NODE *ARGIND_node;
225 extern NODE *ERRNO_node;
226 extern NODE **fields_arr;
228 #if defined(__DJGPP__) || defined(__MINGW32__) || defined(__EMX__) || defined(__CYGWIN__)
229 /* binmode --- convert BINMODE to string for fopen */
232 binmode(const char *mode)
236 if ((BINMODE & 1) != 0)
241 if ((BINMODE & 2) != 0)
242 mode = (mode[0] == 'w' ? "wb" : "ab");
248 #define binmode(mode) (mode)
252 /* File pointers have an extra level of indirection, and there are cases where
253 `stdin' can be null. That can crash gawk if fileno() is used as-is. */
254 static int vmsrtl_fileno(FILE *);
255 static int vmsrtl_fileno(fp) FILE *fp; { return fileno(fp); }
257 #define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1)
261 after_beginfile(IOBUF **curfile)
268 if (iop->fd == INVALID_HANDLE) {
273 errcode = iop->errcode;
279 if (errcode == EISDIR && ! do_traditional) {
280 warning(_("command line argument `%s' is a directory: skipped"), fname);
281 return; /* read next file */
283 fatal(_("cannot open file `%s' for reading (%s)"),
284 fname, strerror(errcode));
288 * Open hooks could have been changed by BEGINFILE,
289 * so delay check until now.
295 /* nextfile --- move to the next input data file */
298 nextfile(IOBUF **curfile, int skipping)
301 static int files = FALSE;
305 int fd = INVALID_HANDLE;
307 IOBUF *iop = *curfile;
309 if (skipping) { /* for 'nextfile' call */
312 errcode = iop->errcode;
313 (void) iop_close(iop);
316 return (errcode == 0);
321 assert(iop->fd != INVALID_HANDLE);
322 (void) iop_close(iop);
324 return 1; /* run endfile block */
329 for (; i < (long) (ARGC_node->lnode->numbr); i++) {
330 tmp = make_number((AWKNUM) i);
331 (void) force_string(tmp);
332 arg = in_array(ARGV_node, tmp);
334 if (arg == NULL || arg->stlen == 0)
336 arg = force_string(arg);
337 arg->stptr[arg->stlen] = '\0';
338 if (! do_traditional) {
339 unref(ARGIND_node->var_value);
340 ARGIND_node->var_value = make_number((AWKNUM) i);
343 if (! arg_assign(arg->stptr, FALSE)) {
347 fd = devopen(fname, binmode("r"));
349 if (! do_traditional)
352 /* This is a kludge. */
353 unref(FILENAME_node->var_value);
354 FILENAME_node->var_value = dupnode(arg);
356 iop = *curfile = iop_alloc(fd, fname, &mybuf, FALSE);
357 if (fd == INVALID_HANDLE)
358 iop->errcode = errcode;
361 iop->flag |= IOP_NOFREE_OBJ;
362 return ++i; /* run beginfile block */
366 if (files == FALSE) {
368 /* no args. -- use stdin */
369 /* FNR is init'ed to 0 */
371 if (! do_traditional)
373 unref(FILENAME_node->var_value);
374 FILENAME_node->var_value = make_string("-", 1);
375 FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */
377 iop = *curfile = iop_alloc(fileno(stdin), fname, &mybuf, FALSE);
378 iop->flag |= IOP_NOFREE_OBJ;
379 if (iop->fd == INVALID_HANDLE) {
383 (void) iop_close(iop);
385 fatal(_("cannot open file `%s' for reading (%s)"),
386 fname, strerror(errcode));
388 return ++i; /* run beginfile block */
391 return -1; /* end of input, run end block or Op_atexit */
394 /* set_FNR --- update internal FNR from awk variable */
399 FNR = (long) FNR_node->var_value->numbr;
402 /* set_NR --- update internal NR from awk variable */
407 NR = (long) NR_node->var_value->numbr;
410 /* inrec --- This reads in a record from the input file */
413 inrec(IOBUF *iop, int *errcode)
419 if (at_eof(iop) && no_data_left(iop))
421 else if ((iop->flag & IOP_CLOSED) != 0)
424 cnt = get_a_record(&begin, iop, errcode);
429 update_ERRNO_saved(*errcode);
433 set_record(begin, cnt);
439 /* remap_std_file --- reopen a standard descriptor on /dev/null */
442 remap_std_file(int oldfd)
448 * Give OS-specific routines in gawkmisc.c chance to interpret
449 * "/dev/null" as appropriate for their platforms.
451 newfd = os_devopen("/dev/null", O_RDWR);
452 if (newfd == INVALID_HANDLE)
453 newfd = open("/dev/null", O_RDWR);
455 /* dup2() will close oldfd for us first. */
456 ret = dup2(newfd, oldfd);
465 /* iop_close --- close an open IOP */
468 iop_close(IOBUF *iop)
474 if (iop->fd == INVALID_HANDLE) { /* from nextfile(...) above */
475 assert(iop->buf == NULL);
476 assert((iop->flag & IOP_NOFREE_OBJ) != 0);
482 iop->flag &= ~IOP_AT_EOF;
483 iop->flag |= IOP_CLOSED; /* there may be dangling pointers */
486 * Closing standard files can cause crufty code elsewhere to lose.
487 * So we remap the standard file to /dev/null.
488 * Thanks to Jim Meyering for the suggestion.
490 if (iop->fd == fileno(stdin)
491 || iop->fd == fileno(stdout)
492 || iop->fd == fileno(stderr))
493 ret = remap_std_file(iop->fd);
495 ret = close(iop->fd);
497 if (iop->close_func != NULL)
498 (*iop->close_func)(iop);
501 warning(_("close of fd %d (`%s') failed (%s)"), iop->fd,
502 iop->name, strerror(errno));
504 * Be careful -- $0 may still reference the buffer even though
505 * an explicit close is being done; in the future, maybe we
506 * can do this a bit better.
509 if ((fields_arr[0]->stptr >= iop->buf)
510 && (fields_arr[0]->stptr < (iop->buf + iop->size))) {
513 t = make_string(fields_arr[0]->stptr,
514 fields_arr[0]->stlen);
515 unref(fields_arr[0]);
518 * 1/27/2003: This used to be here:
522 * Don't do that; reset_record() throws away all fields,
523 * saves FS etc. We just need to make sure memory isn't
524 * corrupted and that references to $0 and fields work.
530 if ((iop->flag & IOP_NOFREE_OBJ) == 0)
532 return ret == -1 ? 1 : 0;
535 /* redflags2str --- turn redirection flags into a string, for debugging */
538 redflags2str(int flags)
540 static const struct flagtab redtab[] = {
541 { RED_FILE, "RED_FILE" },
542 { RED_PIPE, "RED_PIPE" },
543 { RED_READ, "RED_READ" },
544 { RED_WRITE, "RED_WRITE" },
545 { RED_APPEND, "RED_APPEND" },
546 { RED_NOBUF, "RED_NOBUF" },
547 { RED_EOF, "RED_EOF" },
548 { RED_TWOWAY, "RED_TWOWAY" },
549 { RED_PTY, "RED_PTY" },
550 { RED_SOCKET, "RED_SOCKET" },
551 { RED_TCP, "RED_TCP" },
555 return genflags2str(flags, redtab);
558 /* redirect --- Redirection for printf and print commands */
561 redirect(NODE *redir_exp, int redirtype, int *errflg)
567 const char *direction = "to";
570 const char *what = NULL;
572 int len; /* used with /inet */
573 static struct redirect *save_rp = NULL; /* hold onto rp that should
578 fatal(_("redirection not allowed in sandbox mode"));
581 case redirect_append:
584 case redirect_output:
585 outflag = (RED_FILE|RED_WRITE);
587 if (redirtype == redirect_output)
593 tflag = (RED_PIPE|RED_WRITE);
596 case redirect_pipein:
597 tflag = (RED_PIPE|RED_READ);
601 tflag = (RED_FILE|RED_READ);
604 case redirect_twoway:
605 tflag = (RED_READ|RED_WRITE|RED_TWOWAY);
611 if (do_lint && (redir_exp->flags & STRCUR) == 0)
612 lintwarn(_("expression in `%s' redirection only has numeric value"),
614 redir_exp = force_string(redir_exp);
615 str = redir_exp->stptr;
617 if (str == NULL || *str == '\0')
618 fatal(_("expression for `%s' redirection has null string value"),
621 if (do_lint && (strncmp(str, "0", redir_exp->stlen) == 0
622 || strncmp(str, "1", redir_exp->stlen) == 0))
623 lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"),
627 * XXX: Use /inet4 and /inet6 with plain /inet being whatever
628 * we get back from the system.
631 if (inetfile(str, & len, NULL)) {
633 if (strncmp(str + len, "tcp/", 4) == 0)
634 tflag |= RED_TCP; /* use shutdown when closing */
636 #endif /* HAVE_SOCKETS */
638 for (rp = red_head; rp != NULL; rp = rp->next) {
639 #ifndef PIPES_SIMULATED
641 * This is an efficiency hack. We want to
642 * recover the process slot for dead children,
643 * if at all possible. Messing with signal() for
644 * SIGCLD leads to lots of headaches. However, if
645 * we've gotten EOF from a child input pipeline, it's
646 * good bet that the child has died. So recover it.
648 if ((rp->flag & RED_EOF) && redirtype == redirect_pipein) {
652 #endif /* PIPES_SIMULATED */
654 /* now check for a match */
655 if (strlen(rp->value) == redir_exp->stlen
656 && memcmp(rp->value, str, redir_exp->stlen) == 0
657 && ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag
659 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) {
661 int rpflag = (rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY));
662 int newflag = (tflag & ~(RED_NOBUF|RED_EOF|RED_PTY));
664 if (do_lint && rpflag != newflag)
666 _("unnecessary mixing of `>' and `>>' for file `%.*s'"),
667 (int) redir_exp->stlen, rp->value);
675 if (save_rp != NULL) {
679 emalloc(rp, struct redirect *, sizeof(struct redirect), "redirect");
680 emalloc(str, char *, redir_exp->stlen + 1, "redirect");
681 memcpy(str, redir_exp->stptr, redir_exp->stlen);
682 str[redir_exp->stlen] = '\0';
690 str = rp->value; /* get \0 terminated string */
693 while (rp->fp == NULL && rp->iop == NULL) {
694 if (! new_rp && rp->flag & RED_EOF) {
696 * encountered EOF on file or pipe -- must be cleared
697 * by explicit close() before reading more
705 case redirect_output:
707 if ((rp->flag & RED_USED) != 0)
708 mode = (rp->mode[1] == 'b') ? "ab" : "a";
710 case redirect_append:
714 /* synchronize output before new pipe */
717 os_restore_mode(fileno(stdin));
718 if ((rp->fp = popen(str, binmode("w"))) == NULL)
719 fatal(_("can't open pipe `%s' for output (%s)"),
720 str, strerror(errno));
722 /* set close-on-exec */
723 os_close_on_exec(fileno(rp->fp), str, "pipe", "to");
724 rp->flag |= RED_NOBUF;
726 case redirect_pipein:
728 if (gawk_popen(str, rp) == NULL)
729 fatal(_("can't open pipe `%s' for input (%s)"),
730 str, strerror(errno));
734 fd = devopen(str, binmode("r"));
735 if (fd == INVALID_HANDLE && errno == EISDIR) {
737 /* do not free rp, saving it for reuse (save_rp = rp) */
740 rp->iop = iop_alloc(fd, str, NULL, TRUE);
742 case redirect_twoway:
743 direction = "to/from";
744 if (! two_way_open(str, rp)) {
746 if (inetfile(str, NULL, NULL)) {
748 /* do not free rp, saving it for reuse (save_rp = rp) */
752 fatal(_("can't open two way pipe `%s' for input/output (%s)"),
753 str, strerror(errno));
762 fd = devopen(str, mode);
764 if (fd > INVALID_HANDLE) {
765 if (fd == fileno(stdin))
767 else if (fd == fileno(stdout))
769 else if (fd == fileno(stderr))
772 const char *omode = mode;
773 #if defined(F_GETFL) && defined(O_APPEND)
776 fd_flags = fcntl(fd, F_GETFL);
777 if (fd_flags != -1 && (fd_flags & O_APPEND) == O_APPEND)
778 omode = binmode("a");
780 os_close_on_exec(fd, str, "file", "");
781 rp->fp = fdopen(fd, (const char *) omode);
782 rp->mode = (const char *) mode;
783 /* don't leak file descriptors */
787 if (rp->fp != NULL && os_isatty(fd))
788 rp->flag |= RED_NOBUF;
790 /* Move rp to the head of the list. */
791 if (! new_rp && red_head != rp) {
792 if ((rp->prev->next = rp->next) != NULL)
793 rp->next->prev = rp->prev;
802 if (rp->fp == NULL && rp->iop == NULL) {
803 /* too many files open -- close one and try again */
804 if (errno == EMFILE || errno == ENFILE)
806 #if defined __MINGW32__ || defined __sun
807 else if (errno == 0) /* HACK! */
811 /* Alpha/VMS V7.1's C RTL is returning this instead
812 of EMFILE (haven't tried other post-V6.2 systems) */
813 #define SS$_EXQUOTA 0x001C
814 else if (errno == EIO && vaxc$errno == SS$_EXQUOTA)
819 * Some other reason for failure.
821 * On redirection of input from a file,
822 * just return an error, so e.g. getline
823 * can return -1. For output to file,
824 * complain. The shell will complain on
825 * a bad command to a pipe.
829 if (redirtype == redirect_output
830 || redirtype == redirect_append
832 /* multiple messages make life easier for translators */
833 if (*direction == 'f')
834 fatal(_("can't redirect from `%s' (%s)"),
835 str, strerror(errno));
837 fatal(_("can't redirect to `%s' (%s)"),
838 str, strerror(errno));
840 /* do not free rp, saving it for reuse (save_rp = rp) */
849 * It opened successfully, hook it into the list.
850 * Maintain the list in most-recently-used first order.
852 if (red_head != NULL)
862 /* getredirect --- find the struct redirect for this file or pipe */
865 getredirect(const char *str, int len)
869 for (rp = red_head; rp != NULL; rp = rp->next)
870 if (strlen(rp->value) == len && memcmp(rp->value, str, len) == 0)
876 /* close_one --- temporarily close an open file to re-use the fd */
882 struct redirect *rplast = NULL;
884 static short warned = FALSE;
886 if (do_lint && ! warned) {
888 lintwarn(_("reached system limit for open files: starting to multiplex file descriptors"));
891 /* go to end of list first, to pick up least recently used entry */
892 for (rp = red_head; rp != NULL; rp = rp->next)
894 /* now work back up through the list */
895 for (rp = rplast; rp != NULL; rp = rp->prev) {
896 /* don't close standard files! */
897 if (rp->fp == NULL || rp->fp == stderr || rp->fp == stdout)
900 if ((rp->flag & (RED_FILE|RED_WRITE)) == (RED_FILE|RED_WRITE)) {
901 rp->flag |= RED_USED;
903 if (/* do_lint && */ fclose(rp->fp) != 0)
904 warning(_("close of `%s' failed (%s)."),
905 rp->value, strerror(errno));
911 /* surely this is the only reason ??? */
912 fatal(_("too many pipes or input files open"));
915 /* do_close --- completely close an open file or pipe */
922 two_way_close_type how = CLOSE_ALL; /* default */
925 /* 2nd arg if present: "to" or "from" for two-way pipe */
926 /* DO NOT use _() on the strings here! */
928 if (strcasecmp(tmp2->stptr, "to") == 0)
930 else if (strcasecmp(tmp2->stptr, "from") == 0)
934 fatal(_("close: second argument must be `to' or `from'"));
939 tmp = POP_STRING(); /* 1st arg: redir to close */
941 for (rp = red_head; rp != NULL; rp = rp->next) {
942 if (strlen(rp->value) == tmp->stlen
943 && memcmp(rp->value, tmp->stptr, tmp->stlen) == 0)
947 if (rp == NULL) { /* no match, return -1 */
951 lintwarn(_("close: `%.*s' is not an open file, pipe or co-process"),
952 (int) tmp->stlen, tmp->stptr);
954 if (! do_traditional) {
955 /* update ERRNO manually, using errno = ENOENT is a stretch. */
956 cp = _("close of redirection that was never opened");
957 unref(ERRNO_node->var_value);
958 ERRNO_node->var_value = make_string(cp, strlen(cp));
962 return make_number((AWKNUM) -1.0);
965 fflush(stdout); /* synchronize regular output */
966 tmp = make_number((AWKNUM) close_redir(rp, FALSE, how));
969 * POSIX says close() returns 0 on success, non-zero otherwise.
970 * For POSIX, at this point we just return 0. Otherwise we
971 * return the exit status of the process or of pclose(), depending.
972 * This whole business is a mess.
976 return make_number((AWKNUM) 0);
981 /* close_rp --- separate function to just do closing */
984 close_rp(struct redirect *rp, two_way_close_type how)
989 if ((rp->flag & RED_TWOWAY) != 0) { /* two-way pipe */
991 if ((how == CLOSE_ALL || how == CLOSE_TO) && rp->fp != NULL) {
993 if ((rp->flag & RED_TCP) != 0)
994 (void) shutdown(fileno(rp->fp), SHUT_WR);
995 #endif /* HAVE_SOCKETS */
997 if ((rp->flag & RED_PTY) != 0) {
998 fwrite("\004\n", sizeof("\004\n") - 1, 1, rp->fp);
1001 status = fclose(rp->fp);
1006 if (how == CLOSE_ALL || how == CLOSE_FROM) {
1007 if ((rp->flag & RED_SOCKET) != 0 && rp->iop != NULL) {
1009 if ((rp->flag & RED_TCP) != 0)
1010 (void) shutdown(rp->iop->fd, SHUT_RD);
1011 #endif /* HAVE_SOCKETS */
1012 (void) iop_close(rp->iop);
1014 status = gawk_pclose(rp);
1018 } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) { /* write to pipe */
1019 status = pclose(rp->fp);
1020 if ((BINMODE & 1) != 0)
1021 os_setbinmode(fileno(stdin), O_BINARY);
1024 } else if (rp->fp != NULL) { /* write to file */
1025 status = fclose(rp->fp);
1027 } else if (rp->iop != NULL) { /* read from pipe/file */
1028 if ((rp->flag & RED_PIPE) != 0) /* read from pipe */
1029 status = gawk_pclose(rp);
1030 /* gawk_pclose sets rp->iop to null */
1031 else { /* read from file */
1032 status = iop_close(rp->iop);
1040 /* close_redir --- close an open file or pipe */
1043 close_redir(struct redirect *rp, int exitwarn, two_way_close_type how)
1049 if (rp->fp == stdout || rp->fp == stderr)
1050 goto checkwarn; /* bypass closing, remove from list */
1052 if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL)
1053 lintwarn(_("close: redirection `%s' not opened with `|&', second argument ignored"),
1056 status = close_rp(rp, how);
1058 /* SVR4 awk checks and warns about status of close */
1060 int save_errno = errno;
1061 char *s = strerror(save_errno);
1064 * Too many people have complained about this.
1065 * As of 2.15.6, it is now under lint control.
1068 if ((rp->flag & RED_PIPE) != 0)
1069 lintwarn(_("failure status (%d) on pipe close of `%s' (%s)"),
1070 status, rp->value, s);
1072 lintwarn(_("failure status (%d) on file close of `%s' (%s)"),
1073 status, rp->value, s);
1076 if (! do_traditional) {
1077 /* set ERRNO too so that program can get at it */
1078 update_ERRNO_saved(save_errno);
1085 * Don't use lintwarn() here. If lint warnings are fatal,
1086 * doing so prevents us from closing other open redirections.
1088 * Using multiple full messages instead of string parameters
1089 * for the types makes message translation easier.
1091 if ((rp->flag & RED_SOCKET) != 0)
1092 warning(_("no explicit close of socket `%s' provided"),
1094 else if ((rp->flag & RED_TWOWAY) != 0)
1095 warning(_("no explicit close of co-process `%s' provided"),
1097 else if ((rp->flag & RED_PIPE) != 0)
1098 warning(_("no explicit close of pipe `%s' provided"),
1101 warning(_("no explicit close of file `%s' provided"),
1105 /* remove it from the list if closing both or both ends have been closed */
1106 if (how == CLOSE_ALL || (rp->iop == NULL && rp->fp == NULL)) {
1107 if (rp->next != NULL)
1108 rp->next->prev = rp->prev;
1109 if (rp->prev != NULL)
1110 rp->prev->next = rp->next;
1112 red_head = rp->next;
1119 /* flush_io --- flush all open output files */
1124 struct redirect *rp;
1128 if (fflush(stdout)) {
1129 warning(_("error writing standard output (%s)"), strerror(errno));
1132 if (fflush(stderr)) {
1133 warning(_("error writing standard error (%s)"), strerror(errno));
1136 for (rp = red_head; rp != NULL; rp = rp->next)
1137 /* flush both files and pipes, what the heck */
1138 if ((rp->flag & RED_WRITE) && rp->fp != NULL) {
1139 if (fflush(rp->fp)) {
1140 if (rp->flag & RED_PIPE)
1141 warning(_("pipe flush of `%s' failed (%s)."),
1142 rp->value, strerror(errno));
1143 else if (rp->flag & RED_TWOWAY)
1144 warning(_("co-process flush of pipe to `%s' failed (%s)."),
1145 rp->value, strerror(errno));
1147 warning(_("file flush of `%s' failed (%s)."),
1148 rp->value, strerror(errno));
1153 status = -1; /* canonicalize it */
1157 /* close_io --- close all open files, called when exiting */
1160 close_io(int *stdio_problem)
1162 struct redirect *rp;
1163 struct redirect *next;
1167 for (rp = red_head; rp != NULL; rp = next) {
1170 * close_redir() will print a message if needed
1171 * if do_lint, warn about lack of explicit close
1173 if (close_redir(rp, do_lint, CLOSE_ALL))
1178 * Some of the non-Unix os's have problems doing an fclose
1179 * on stdout and stderr. Since we don't really need to close
1180 * them, we just flush them, and do that across the board.
1182 *stdio_problem = FALSE;
1183 if (fflush(stdout)) {
1184 warning(_("error writing standard output (%s)"), strerror(errno));
1186 *stdio_problem = TRUE;
1188 if (fflush(stderr)) {
1189 warning(_("error writing standard error (%s)"), strerror(errno));
1191 *stdio_problem = TRUE;
1196 /* str2mode --- convert a string mode to an integer mode */
1199 str2mode(const char *mode)
1202 const char *second = & mode[1];
1210 if (*second == '+' || *second == 'w')
1215 ret = O_WRONLY|O_CREAT|O_TRUNC;
1216 if (*second == '+' || *second == 'r')
1217 ret = O_RDWR|O_CREAT|O_TRUNC;
1221 ret = O_WRONLY|O_APPEND|O_CREAT;
1223 ret = O_RDWR|O_APPEND|O_CREAT;
1230 if (strchr(mode, 'b') != NULL)
1237 /* socketopen --- open a socket and set it into connected state */
1240 socketopen(int family, int type, const char *localpname,
1241 const char *remotepname, const char *remotehostname)
1243 struct addrinfo *lres, *lres0;
1244 struct addrinfo lhints;
1245 struct addrinfo *rres, *rres0;
1246 struct addrinfo rhints;
1251 int socket_fd = INVALID_HANDLE;
1252 int any_remote_host = (strcmp(remotehostname, "0") == 0);
1254 memset (&lhints, '\0', sizeof (lhints));
1255 lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
1256 lhints.ai_socktype = type;
1257 lhints.ai_family = family;
1259 lerror = getaddrinfo (NULL, localpname, &lhints, &lres);
1261 if (strcmp(localpname, "0") != 0)
1262 fatal(_("local port %s invalid in `/inet'"), localpname);
1268 while (lres != NULL) {
1269 memset (&rhints, '\0', sizeof (rhints));
1270 rhints.ai_flags = lhints.ai_flags;
1271 rhints.ai_socktype = lhints.ai_socktype;
1272 rhints.ai_family = lhints.ai_family;
1273 rhints.ai_protocol = lhints.ai_protocol;
1275 rerror = getaddrinfo (any_remote_host ? NULL : remotehostname, remotepname, &rhints, &rres);
1278 freeaddrinfo(lres0);
1279 fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname);
1282 socket_fd = INVALID_HANDLE;
1283 while (rres != NULL) {
1284 socket_fd = socket(rres->ai_family,
1285 rres->ai_socktype, rres->ai_protocol);
1286 if (socket_fd < 0 || socket_fd == INVALID_HANDLE)
1289 if (type == SOCK_STREAM) {
1292 struct linger linger;
1293 memset(& linger, '\0', sizeof(linger));
1295 setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
1296 (char *) & on, sizeof(on));
1299 linger.l_linger = 30; /* linger for 30/100 second */
1300 setsockopt(socket_fd, SOL_SOCKET, SO_LINGER,
1301 (char *) & linger, sizeof(linger));
1304 if (bind(socket_fd, lres->ai_addr, lres->ai_addrlen) != 0)
1307 if (! any_remote_host) { /* not ANY => create a client */
1308 if (connect(socket_fd, rres->ai_addr, rres->ai_addrlen) == 0)
1310 } else { /* remote host is ANY => create a server */
1311 if (type == SOCK_STREAM) {
1312 int clientsocket_fd = INVALID_HANDLE;
1314 struct sockaddr_storage remote_addr;
1315 socklen_t namelen = sizeof (remote_addr);
1317 if (listen(socket_fd, 1) >= 0
1318 && (clientsocket_fd = accept(socket_fd,
1319 (struct sockaddr *) &remote_addr,
1322 socket_fd = clientsocket_fd;
1325 } else if (type == SOCK_DGRAM) {
1328 struct sockaddr_storage remote_addr;
1331 if (recvfrom(socket_fd, buf, 1, MSG_PEEK,
1332 (struct sockaddr *) & remote_addr,
1335 && connect(socket_fd,
1336 (struct sockaddr *)& remote_addr,
1344 if (socket_fd != INVALID_HANDLE)
1346 socket_fd = INVALID_HANDLE;
1347 rres = rres->ai_next;
1349 freeaddrinfo(rres0);
1350 if (socket_fd != INVALID_HANDLE)
1352 lres = lres->ai_next;
1355 freeaddrinfo(lres0);
1359 #endif /* HAVE_SOCKETS */
1361 /* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
1364 * Strictly speaking, "name" is not a "const char *" because we temporarily
1365 * change the string.
1369 devopen(const char *name, const char *mode)
1378 flag = str2mode(mode);
1380 if (strcmp(name, "-") == 0)
1381 return fileno(stdin);
1383 openfd = INVALID_HANDLE;
1388 if ((openfd = os_devopen(name, flag)) != INVALID_HANDLE) {
1389 os_close_on_exec(openfd, name, "file", "");
1393 if (strncmp(name, "/dev/", 5) == 0) {
1394 cp = (char *) name + 5;
1396 if (strcmp(cp, "stdin") == 0 && (flag & O_ACCMODE) == O_RDONLY)
1397 openfd = fileno(stdin);
1398 else if (strcmp(cp, "stdout") == 0 && (flag & O_ACCMODE) == O_WRONLY)
1399 openfd = fileno(stdout);
1400 else if (strcmp(cp, "stderr") == 0 && (flag & O_ACCMODE) == O_WRONLY)
1401 openfd = fileno(stderr);
1402 else if (strncmp(cp, "fd/", 3) == 0) {
1406 openfd = (int) strtoul(cp, &ptr, 10);
1407 if (openfd <= INVALID_HANDLE || ptr == cp
1408 || fstat(openfd, &sbuf) < 0)
1409 openfd = INVALID_HANDLE;
1411 /* do not set close-on-exec for inherited fd's */
1412 if (openfd != INVALID_HANDLE)
1414 } else if (inetfile(name, & len, & family)) {
1416 /* /inet/protocol/localport/hostname/remoteport */
1419 char *hostnameslastcharp;
1421 char *localpnamelastcharp;
1423 cp = (char *) name + len;
1424 /* which protocol? */
1425 if (strncmp(cp, "tcp/", 4) == 0)
1426 protocol = SOCK_STREAM;
1427 else if (strncmp(cp, "udp/", 4) == 0)
1428 protocol = SOCK_DGRAM;
1430 protocol = SOCK_STREAM; /* shut up the compiler */
1431 fatal(_("no (known) protocol supplied in special filename `%s'"),
1436 /* which localport? */
1438 while (*cp != '/' && *cp != '\0')
1441 * Require a port, let them explicitly put 0 if
1444 if (*cp != '/' || cp == localpname)
1445 fatal(_("special file name `%s' is incomplete"), name);
1448 * We change the special file name temporarily because we
1449 * need a 0-terminated string here for conversion with atoi().
1450 * By using atoi() the use of decimal numbers is enforced.
1453 localpnamelastcharp = cp;
1455 /* which hostname? */
1458 while (*cp != '/' && *cp != '\0')
1460 if (*cp != '/' || cp == hostname) {
1461 *localpnamelastcharp = '/';
1462 fatal(_("must supply a remote hostname to `/inet'"));
1465 hostnameslastcharp = cp;
1467 /* which remoteport? */
1470 * The remote port ends the special file name.
1471 * This means there already is a 0 at the end of the string.
1472 * Therefore no need to patch any string ending.
1474 * Here too, require a port, let them explicitly put 0 if
1478 *localpnamelastcharp = '/';
1479 *hostnameslastcharp = '/';
1480 fatal(_("must supply a remote port to `/inet'"));
1484 #define DEFAULT_RETRIES 20
1485 static unsigned long def_retries = DEFAULT_RETRIES;
1486 static int first_time = TRUE;
1487 unsigned long retries = 0;
1488 static long msleep = 1000;
1492 unsigned long count = 0;
1496 if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) {
1497 count = strtoul(cp, &end, 10);
1498 if (end != cp && count > 0)
1499 def_retries = count;
1503 * Env var is in milliseconds, paramter to usleep()
1504 * is microseconds, make the conversion. Default is
1507 if ((ms2 = getenv("GAWK_MSEC_SLEEP")) != NULL) {
1508 msleep = strtol(ms2, &end, 10);
1509 if (end == ms2 || msleep < 0)
1515 retries = def_retries;
1518 openfd = socketopen(family, protocol, localpname, cp, hostname);
1520 } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0);
1523 *localpnamelastcharp = '/';
1524 *hostnameslastcharp = '/';
1525 #else /* ! HAVE_SOCKETS */
1526 fatal(_("TCP/IP communications are not supported"));
1527 #endif /* HAVE_SOCKETS */
1531 if (openfd == INVALID_HANDLE)
1532 openfd = open(name, flag, 0666);
1534 if (openfd == INVALID_HANDLE && errno == EACCES) {
1535 /* on OS/2 directory access via open() is not permitted */
1538 if (stat(name, &buf) == 0 && S_ISDIR(buf.st_mode))
1542 if (openfd != INVALID_HANDLE) {
1543 if (os_isdir(openfd)) {
1544 (void) close(openfd); /* don't leak fds */
1545 /* Set useful error number. */
1547 return INVALID_HANDLE;
1550 if (openfd > fileno(stderr))
1551 os_close_on_exec(openfd, name, "file", "");
1554 * XXX: FIXME: if fd is INVALID_HANDLE, see if an open hook
1560 /* two_way_open --- open a two way communications channel */
1563 two_way_open(const char *str, struct redirect *rp)
1565 static int no_ptys = FALSE;
1568 /* case 1: socket */
1569 if (inetfile(str, NULL, NULL)) {
1572 fd = devopen(str, "rw");
1573 if (fd == INVALID_HANDLE)
1575 rp->fp = fdopen(fd, "w");
1576 if (rp->fp == NULL) {
1585 os_close_on_exec(newfd, str, "socket", "to/from");
1586 rp->iop = iop_alloc(newfd, str, NULL, TRUE);
1587 if (rp->iop == NULL) {
1591 rp->flag |= RED_SOCKET;
1594 #endif /* HAVE_SOCKETS */
1596 #if defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS)
1597 /* case 2: use ptys for two-way communications to child */
1598 if (! no_ptys && pty_vs_pipe(str)) {
1599 static int initialized = FALSE;
1600 static char first_pty_letter;
1602 static int have_dev_ptmx;
1606 int master, dup_master;
1612 /* Use array of chars to avoid ascii / ebcdic issues */
1613 static char pty_chars[] = "pqrstuvwxyzabcdefghijklmno";
1616 if (! initialized) {
1619 have_dev_ptmx = (stat("/dev/ptmx", &statb) >= 0);
1624 sprintf(slavenam, "/dev/pty%c0", c);
1625 if (stat(slavenam, &statb) >= 0) {
1626 first_pty_letter = c;
1629 } while (pty_chars[i] != '\0');
1633 if (have_dev_ptmx) {
1634 master = open("/dev/ptmx", O_RDWR);
1640 tem = ptsname(master);
1642 strcpy(slavenam, tem);
1645 (void) close(master);
1650 if (first_pty_letter) {
1652 * Assume /dev/ptyXNN and /dev/ttyXN naming system.
1653 * The FIRST_PTY_LETTER gives the first X to try. We try in the
1654 * sequence FIRST_PTY_LETTER, .., 'z', 'a', .., FIRST_PTY_LETTER.
1655 * Is this worthwhile, or just over-zealous?
1657 c = first_pty_letter;
1662 for (i = 0; i < 16; i++) {
1663 sprintf(slavenam, "/dev/pty%c%x", c, i);
1664 if (stat(slavenam, &statb) < 0) {
1665 no_ptys = TRUE; /* bypass all this next time */
1669 if ((master = open(slavenam, O_RDWR)) >= 0) {
1670 slavenam[sizeof("/dev/") - 1] = 't';
1671 if (access(slavenam, R_OK | W_OK) == 0)
1676 /* move to next character */
1677 cp = strchr(pty_chars, c);
1683 } while (c != first_pty_letter);
1687 /* Couldn't find a pty. Fall back to using pipes. */
1691 if ((slave = open(slavenam, O_RDWR)) < 0) {
1693 fatal(_("could not open `%s', mode `%s'"),
1699 * Push the necessary modules onto the slave to
1700 * get terminal semantics.
1702 ioctl(slave, I_PUSH, "ptem");
1703 ioctl(slave, I_PUSH, "ldterm");
1706 tcgetattr(slave, &st);
1707 st.c_iflag &= ~(ISTRIP | IGNCR | INLCR | IXOFF);
1708 st.c_iflag |= (ICRNL | IGNPAR | BRKINT | IXON);
1709 st.c_oflag &= ~OPOST;
1710 st.c_cflag &= ~CSIZE;
1711 st.c_cflag |= CREAD | CS8 | CLOCAL;
1712 st.c_lflag &= ~(ECHO | ECHOE | ECHOK | NOFLSH | TOSTOP);
1719 /* Set some control codes to default values */
1721 st.c_cc[VINTR] = '\003'; /* ^c */
1724 st.c_cc[VQUIT] = '\034'; /* ^| */
1727 st.c_cc[VERASE] = '\177'; /* ^? */
1730 st.c_cc[VKILL] = '\025'; /* ^u */
1733 st.c_cc[VEOF] = '\004'; /* ^d */
1735 tcsetattr(slave, TCSANOW, &st);
1737 switch (pid = fork ()) {
1743 ioctl(slave, TIOCSCTTY, 0);
1746 if (close(master) == -1)
1747 fatal(_("close of master pty failed (%s)"), strerror(errno));
1749 fatal(_("close of stdout in child failed (%s)"),
1751 if (dup(slave) != 1)
1752 fatal(_("moving slave pty to stdout in child failed (dup: %s)"), strerror(errno));
1754 fatal(_("close of stdin in child failed (%s)"),
1756 if (dup(slave) != 0)
1757 fatal(_("moving slave pty to stdin in child failed (dup: %s)"), strerror(errno));
1759 fatal(_("close of slave pty failed (%s)"), strerror(errno));
1761 /* stderr does NOT get dup'ed onto child's stdout */
1763 signal(SIGPIPE, SIG_DFL);
1765 execl("/bin/sh", "sh", "-c", str, NULL);
1766 _exit(errno == ENOENT ? 127 : 126);
1779 (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */
1780 fatal(_("close of slave pty failed (%s)"), strerror(errno));
1784 rp->iop = iop_alloc(master, str, NULL, TRUE);
1785 if (rp->iop == NULL) {
1786 (void) close(master);
1787 (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */
1792 * Force read and write ends of two-way connection to
1793 * be different fd's so they can be closed independently.
1795 if ((dup_master = dup(master)) < 0
1796 || (rp->fp = fdopen(dup_master, "w")) == NULL) {
1799 (void) close(master);
1800 (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */
1802 (void) close(dup_master);
1805 rp->flag |= RED_PTY;
1806 os_close_on_exec(master, str, "pipe", "from");
1807 os_close_on_exec(dup_master, str, "pipe", "to");
1808 first_pty_letter = '\0'; /* reset for next command */
1811 #endif /* defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS) */
1814 #ifndef PIPES_SIMULATED /* real pipes */
1815 /* case 3: two way pipe to a child process */
1817 int ptoc[2], ctop[2];
1821 int save_stdout, save_stdin;
1825 return FALSE; /* errno set, diagnostic from caller */
1827 if (pipe(ctop) < 0) {
1836 save_stdin = dup(0); /* duplicate stdin */
1837 save_stdout = dup(1); /* duplicate stdout */
1839 if (save_stdout == -1 || save_stdin == -1) {
1840 /* if an error occurrs close all open file handles */
1842 if (save_stdin != -1)
1844 if (save_stdout != -1)
1846 close(ptoc[0]); close(ptoc[1]);
1847 close(ctop[0]); close(ctop[1]);
1852 /* connect pipes to stdin and stdout */
1853 close(1); /* close stdout */
1854 if (dup(ctop[1]) != 1) { /* connect pipe input to stdout */
1855 close(save_stdin); close(save_stdout);
1856 close(ptoc[0]); close(ptoc[1]);
1857 close(ctop[0]); close(ctop[1]);
1858 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
1860 close(0); /* close stdin */
1861 if (dup(ptoc[0]) != 0) { /* connect pipe output to stdin */
1862 close(save_stdin); close(save_stdout);
1863 close(ptoc[0]); close(ptoc[1]);
1864 close(ctop[0]); close(ctop[1]);
1865 fatal(_("moving pipe to stdin in child failed (dup: %s)"), strerror(errno));
1868 /* none of these handles must be inherited by the child process */
1869 (void) close(ptoc[0]); /* close pipe output, child will use stdin instead */
1870 (void) close(ctop[1]); /* close pipe input, child will use stdout instead */
1872 os_close_on_exec(ptoc[1], str, "pipe", "from"); /* pipe input: output of the parent process */
1873 os_close_on_exec(ctop[0], str, "pipe", "from"); /* pipe output: input of the parent process */
1874 os_close_on_exec(save_stdin, str, "pipe", "from"); /* saved stdin of the parent process */
1875 os_close_on_exec(save_stdout, str, "pipe", "from"); /* saved stdout of the parent process */
1877 /* stderr does NOT get dup'ed onto child's stdout */
1878 pid = spawnl(P_NOWAIT, "/bin/sh", "sh", "-c", str, NULL);
1880 /* restore stdin and stdout */
1882 if (dup(save_stdout) != 1) {
1883 close(save_stdin); close(save_stdout);
1884 close(ptoc[1]); close(ctop[0]);
1885 fatal(_("restoring stdout in parent process failed\n"));
1890 if (dup(save_stdin) != 0) {
1892 close(ptoc[1]); close(ctop[0]);
1893 fatal(_("restoring stdin in parent process failed\n"));
1897 if (pid < 0) { /* spawnl() failed */
1906 #else /* NOT __EMX__ */
1907 if ((pid = fork()) < 0) {
1909 close(ptoc[0]); close(ptoc[1]);
1910 close(ctop[0]); close(ctop[1]);
1915 if (pid == 0) { /* child */
1917 fatal(_("close of stdout in child failed (%s)"),
1919 if (dup(ctop[1]) != 1)
1920 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
1922 fatal(_("close of stdin in child failed (%s)"),
1924 if (dup(ptoc[0]) != 0)
1925 fatal(_("moving pipe to stdin in child failed (dup: %s)"), strerror(errno));
1926 if ( close(ptoc[0]) == -1 || close(ptoc[1]) == -1
1927 || close(ctop[0]) == -1 || close(ctop[1]) == -1)
1928 fatal(_("close of pipe failed (%s)"), strerror(errno));
1929 /* stderr does NOT get dup'ed onto child's stdout */
1930 execl("/bin/sh", "sh", "-c", str, NULL);
1931 _exit(errno == ENOENT ? 127 : 126);
1933 #endif /* NOT __EMX__ */
1937 rp->iop = iop_alloc(ctop[0], str, NULL, TRUE);
1938 if (rp->iop == NULL) {
1939 (void) close(ctop[0]);
1940 (void) close(ctop[1]);
1941 (void) close(ptoc[0]);
1942 (void) close(ptoc[1]);
1943 (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */
1947 rp->fp = fdopen(ptoc[1], "w");
1948 if (rp->fp == NULL) {
1951 (void) close(ctop[0]);
1952 (void) close(ctop[1]);
1953 (void) close(ptoc[0]);
1954 (void) close(ptoc[1]);
1955 (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */
1961 os_close_on_exec(ctop[0], str, "pipe", "from");
1962 os_close_on_exec(ptoc[1], str, "pipe", "from");
1964 (void) close(ptoc[0]);
1965 (void) close(ctop[1]);
1971 #else /*PIPES_SIMULATED*/
1973 fatal(_("`|&' not supported"));
1980 #ifndef PIPES_SIMULATED /* real pipes */
1982 /* wait_any --- wait for a child process, close associated pipe */
1985 wait_any(int interesting) /* pid of interest, if any */
1987 RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int);
1990 struct redirect *redp;
1992 hstat = signal(SIGHUP, SIG_IGN);
1993 istat = signal(SIGINT, SIG_IGN);
1994 qstat = signal(SIGQUIT, SIG_IGN);
1996 #ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */
1997 pid = wait(&status);
1999 pid = wait((union wait *)&status);
2001 if (interesting && pid == interesting) {
2003 } else if (pid != -1) {
2004 for (redp = red_head; redp != NULL; redp = redp->next)
2005 if (pid == redp->pid) {
2007 redp->status = status;
2011 if (pid == -1 && errno == ECHILD)
2014 signal(SIGHUP, hstat);
2015 signal(SIGINT, istat);
2016 signal(SIGQUIT, qstat);
2020 /* gawk_popen --- open an IOBUF on a child process */
2023 gawk_popen(const char *cmd, struct redirect *rp)
2032 * used to wait for any children to synchronize input and output,
2033 * but this could cause gawk to hang when it is started in a pipeline
2034 * and thus has a child process feeding it input (shell dependent)
2036 /*(void) wait_any(0);*/ /* wait for outstanding processes */
2039 fatal(_("cannot open pipe `%s' (%s)"), cmd, strerror(errno));
2042 save_stdout = dup(1); /* save stdout */
2044 if (save_stdout == -1) {
2045 close(p[0]); close(p[1]);
2046 return rp->iop; /* failed */
2049 close(1); /* close stdout */
2050 if (dup(p[1]) != 1) {
2051 close(p[0]); close(p[1]);
2052 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
2055 /* none of these handles must be inherited by the child process */
2056 close(p[1]); /* close pipe input */
2058 os_close_on_exec(p[0], cmd, "pipe", "from"); /* pipe output: input of the parent process */
2059 os_close_on_exec(save_stdout, cmd, "pipe", "from"); /* saved stdout of the parent process */
2061 pid = spawnl(P_NOWAIT, "/bin/sh", "sh", "-c", cmd, NULL);
2063 /* restore stdout */
2065 if (dup(save_stdout) != 1) {
2067 fatal(_("restoring stdout in parent process failed\n"));
2071 #else /* NOT __EMX__ */
2072 if ((pid = fork()) == 0) {
2074 fatal(_("close of stdout in child failed (%s)"),
2077 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
2078 if (close(p[0]) == -1 || close(p[1]) == -1)
2079 fatal(_("close of pipe failed (%s)"), strerror(errno));
2080 execl("/bin/sh", "sh", "-c", cmd, NULL);
2081 _exit(errno == ENOENT ? 127 : 126);
2083 #endif /* NOT __EMX__ */
2086 close(p[0]); close(p[1]);
2087 fatal(_("cannot create child process for `%s' (fork: %s)"), cmd, strerror(errno));
2091 if (close(p[1]) == -1) {
2093 fatal(_("close of pipe failed (%s)"), strerror(errno));
2096 os_close_on_exec(p[0], cmd, "pipe", "from");
2097 rp->iop = iop_alloc(p[0], cmd, NULL, TRUE);
2098 if (rp->iop == NULL)
2104 /* gawk_pclose --- close an open child pipe */
2107 gawk_pclose(struct redirect *rp)
2109 if (rp->iop != NULL)
2110 (void) iop_close(rp->iop);
2113 /* process previously found, return stored status */
2116 rp->status = wait_any(rp->pid);
2121 #else /* PIPES_SIMULATED */
2124 * use temporary file rather than pipe
2125 * except if popen() provides real pipes too
2128 /* gawk_popen --- open an IOBUF on a child process */
2131 gawk_popen(const char *cmd, struct redirect *rp)
2135 os_restore_mode(fileno(stdin));
2136 current = popen(cmd, binmode("r"));
2137 if ((BINMODE & 1) != 0)
2138 os_setbinmode(fileno(stdin), O_BINARY);
2139 if (current == NULL)
2141 os_close_on_exec(fileno(current), cmd, "pipe", "from");
2142 rp->iop = iop_alloc(fileno(current), cmd, NULL, TRUE);
2143 if (rp->iop == NULL) {
2144 (void) pclose(current);
2151 /* gawk_pclose --- close an open child pipe */
2154 gawk_pclose(struct redirect *rp)
2156 int rval, aval, fd = rp->iop->fd;
2158 if (rp->iop != NULL) {
2159 rp->iop->fd = dup(fd); /* kludge to allow close() + pclose() */
2160 rval = iop_close(rp->iop);
2163 aval = pclose(rp->ifp);
2165 return (rval < 0 ? rval : aval);
2168 #endif /* PIPES_SIMULATED */
2170 /* do_getline --- read in a line, into var and with redirection */
2173 do_getline_redir(int intovar, int redirtype)
2175 struct redirect *rp = NULL;
2180 NODE *redir_exp = NULL;
2182 int redir_error = 0;
2185 lhs = POP_ADDRESS();
2187 assert(redirtype != 0);
2189 rp = redirect(redir_exp, redirtype, &redir_error);
2193 if (redir_error) { /* failed redirect */
2194 if (! do_traditional)
2195 update_ERRNO_saved(redir_error);
2197 return make_number((AWKNUM) -1.0);
2200 if (iop == NULL) /* end of input */
2201 return make_number((AWKNUM) 0.0);
2204 cnt = get_a_record(&s, iop, &errcode);
2206 if (! do_traditional && (errcode != -1))
2207 update_ERRNO_saved(errcode);
2208 return make_number((AWKNUM) -1.0);
2213 * Don't do iop_close() here if we are
2214 * reading from a pipe; otherwise
2215 * gawk_pclose will not be called.
2217 if ((rp->flag & (RED_PIPE|RED_TWOWAY)) == 0) {
2218 (void) iop_close(iop);
2221 rp->flag |= RED_EOF; /* sticky EOF */
2222 return make_number((AWKNUM) 0.0);
2225 if (lhs == NULL) /* no optional var. */
2227 else { /* assignment to variable */
2229 *lhs = make_string(s, cnt);
2230 (*lhs)->flags |= MAYBE_NUM;
2233 return make_number((AWKNUM) 1.0);
2236 /* do_getline --- read in a line, into var and without redirection */
2239 do_getline(int intovar, IOBUF *iop)
2245 if (iop == NULL) { /* end of input */
2247 (void) POP_ADDRESS();
2248 return make_number((AWKNUM) 0.0);
2252 cnt = get_a_record(&s, iop, &errcode);
2254 if (! do_traditional && (errcode != -1))
2255 update_ERRNO_saved(errcode);
2257 (void) POP_ADDRESS();
2258 return make_number((AWKNUM) -1.0);
2262 return NULL; /* try next file */
2266 if (! intovar) /* no optional var. */
2268 else { /* assignment to variable */
2270 lhs = POP_ADDRESS();
2272 *lhs = make_string(s, cnt);
2273 (*lhs)->flags |= MAYBE_NUM;
2275 return make_number((AWKNUM) 1.0);
2279 static char **awkpath = NULL; /* array containing library search paths */
2280 static int max_pathlen; /* length of the longest item in awkpath */
2282 /* init_awkpath --- split path(=$AWKPATH) into components */
2285 init_awkpath(char *path)
2287 char *start, *end, *p;
2289 static int max_path = 0;
2294 if (path == NULL || *path == '\0')
2297 for (i = 0; i < max_path && awkpath[i]; i++) {
2302 if (max_path == 0) {
2303 max_path = INC_PATH;
2304 emalloc(awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath");
2305 memset(awkpath, 0, (max_path + 1) * sizeof(char *));
2311 while (*end && *end != envsep)
2315 emalloc(p, char *, len + 2, "init_awkpath");
2316 memcpy(p, start, len);
2318 /* add directory punctuation if necessary */
2319 if (! isdirpunct(*(end - 1)))
2323 if (i == max_path) {
2324 max_path += INC_PATH;
2325 erealloc(awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath");
2326 memset(awkpath + i, 0, (INC_PATH + 1) * sizeof(char *));
2329 if (len > max_pathlen)
2333 /* skip one or more envsep char */
2334 while (*end && *end == envsep)
2343 /* do_find_source --- search $AWKPATH for file, return NULL if not found */
2346 do_find_source(const char *src, struct stat *stb, int *errcode)
2351 assert(errcode != NULL);
2353 /* some kind of path name, no search */
2355 emalloc(path, char *, strlen(src) + 1, "do_find_source");
2357 if (stat(path, stb) == 0)
2364 /* try current directory before path search */
2365 if (stat(src, stb) == 0) {
2366 emalloc(path, char *, strlen(src) + 1, "do_find_source");
2371 if (awkpath == NULL)
2372 init_awkpath(getenv("AWKPATH"));
2374 emalloc(path, char *, max_pathlen + strlen(src) + 1, "do_find_source");
2375 for (i = 0; awkpath[i] != NULL; i++) {
2376 if (strcmp(awkpath[i], "./") == 0 || strcmp(awkpath[i], ".") == 0) {
2379 strcpy(path, awkpath[i]);
2381 if (stat(path, stb) == 0)
2385 /* not found, give up */
2391 /* find_source --- find source file with default file extension handling */
2394 find_source(const char *src, struct stat *stb, int *errcode)
2399 if (src == NULL || *src == '\0')
2401 path = do_find_source(src, stb, errcode);
2403 #ifdef DEFAULT_FILETYPE
2404 if (! do_traditional && path == NULL) {
2408 int vms_save = vaxc$errno;
2411 /* append ".awk" and try again */
2412 emalloc(file_awk, char *, strlen(src) +
2413 sizeof(DEFAULT_FILETYPE) + 1, "find_source");
2414 sprintf(file_awk, "%s%s", src, DEFAULT_FILETYPE);
2415 path = do_find_source(file_awk, stb, errcode);
2420 vaxc$errno = vms_save;
2424 #endif /*DEFAULT_FILETYPE*/
2429 /* srcopen --- open source file */
2434 if (s->stype == SRC_STDIN)
2436 if (s->stype == SRC_FILE || s->stype == SRC_INC)
2437 return devopen(s->fullpath, "r");
2438 return INVALID_HANDLE;
2445 fatal(const char *s)
2452 /* open hooks, mainly for use by extension functions */
2454 static struct open_hook {
2455 struct open_hook *next;
2456 void *(*open_func)(IOBUF *);
2459 /* register_open_hook --- add an open hook to the list */
2462 register_open_hook(void *(*open_func)(IOBUF *))
2464 struct open_hook *oh;
2466 emalloc(oh, struct open_hook *, sizeof(*oh), "register_open_hook");
2467 oh->open_func = open_func;
2468 oh->next = open_hooks;
2472 /* find_open_hook --- search the list of open hooks */
2475 find_open_hook(IOBUF *iop)
2477 struct open_hook *oh;
2479 /* walk through open hooks, stop at first one that responds */
2480 for (oh = open_hooks; oh != NULL; oh = oh->next) {
2481 if ((iop->opaque = (*oh->open_func)(iop)) != NULL)
2486 /* iop_alloc --- allocate an IOBUF structure for an open fd */
2489 iop_alloc(int fd, const char *name, IOBUF *iop, int do_openhooks)
2492 int iop_malloced = FALSE;
2495 emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
2496 iop_malloced = TRUE;
2498 memset(iop, '\0', sizeof(IOBUF));
2504 find_open_hook(iop);
2505 else if (iop->fd == INVALID_HANDLE)
2508 /* test reached if tried to find open hook and could not */
2509 if (iop->fd == INVALID_HANDLE) {
2515 if (os_isatty(iop->fd))
2516 iop->flag |= IOP_IS_TTY;
2517 iop->readsize = iop->size = optimal_bufsize(iop->fd, & sbuf);
2519 if (do_lint && S_ISREG(sbuf.st_mode) && sbuf.st_size == 0)
2520 lintwarn(_("data file `%s' is empty"), name);
2522 iop->count = iop->scanoff = 0;
2523 emalloc(iop->buf, char *, iop->size += 2, "iop_alloc");
2524 iop->off = iop->buf;
2525 iop->dataend = NULL;
2526 iop->end = iop->buf + iop->size;
2527 iop->flag |= IOP_AT_START;
2531 #define set_RT_to_null() \
2532 (void)(! do_traditional && (unref(RT_node->var_value), \
2533 RT_node->var_value = Nnull_string))
2535 #define set_RT(str, len) \
2536 (void)(! do_traditional && (unref(RT_node->var_value), \
2537 RT_node->var_value = make_string(str, len)))
2539 /* grow must increase size of buffer, set end, make sure off and dataend point at */
2544 /* grow_iop_buffer --- grow the buffer */
2547 grow_iop_buffer(IOBUF *iop)
2549 size_t valid = iop->dataend - iop->off;
2550 size_t off = iop->off - iop->buf;
2554 * Lop off original extra two bytes, double the size,
2557 newsize = ((iop->size - 2) * 2) + 2;
2559 /* Check for overflow */
2560 if (newsize <= iop->size)
2561 fatal(_("could not allocate more input memory"));
2563 /* Make sure there's room for a disk block */
2564 if (newsize - valid < iop->readsize)
2565 newsize += iop->readsize + 2;
2567 /* Check for overflow, again */
2568 if (newsize <= iop->size)
2569 fatal(_("could not allocate more input memory"));
2571 iop->size = newsize;
2572 erealloc(iop->buf, char *, iop->size, "grow_iop_buffer");
2573 iop->off = iop->buf + off;
2574 iop->dataend = iop->off + valid;
2575 iop->end = iop->buf + iop->size;
2578 /* Here are the routines. */
2582 /* rs1scan --- scan for a single character record terminator */
2585 rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
2594 memset(recm, '\0', sizeof(struct recmatch));
2596 *(iop->dataend) = rs; /* set sentinel */
2597 recm->start = iop->off; /* beginning of record */
2600 if (*state == INDATA) /* skip over data we've already seen */
2605 * From: Bruno Haible <bruno@clisp.org>
2606 * To: Aharon Robbins <arnold@skeeve.com>, gnits@gnits.org
2607 * Subject: Re: multibyte locales: any way to find if a character isn't multibyte?
2608 * Date: Mon, 23 Jun 2003 12:20:16 +0200
2609 * Cc: isamu@yamato.ibm.com
2613 * > Is there any way to make the following query to the current locale?
2615 * > Given an 8-bit value, can this value ever appear as part of
2616 * > a multibyte character?
2618 * There is no simple answer here. The easiest solution I see is to
2619 * get the current locale's codeset (via locale_charset() which is a
2620 * wrapper around nl_langinfo(CODESET)), and then perform a case-by-case
2621 * treatment of the known multibyte encodings, from GB2312 to EUC-JISX0213;
2622 * for the unibyte encodings, a single btowc() call will tell you.
2624 * > This is particularly critical for me for ASCII newline ('\n'). If I
2625 * > can be guaranteed that it never shows up as part of a multibyte character,
2626 * > I can speed up gawk considerably in mulitbyte locales.
2628 * This is much simpler to answer!
2629 * In all ASCII based multibyte encodings used for locales today (this
2630 * excludes EBCDIC based doublebyte encodings from IBM, and also excludes
2631 * ISO-2022-JP which is used for email exchange but not as a locale encoding)
2632 * ALL bytes in the range 0x00..0x2F occur only as a single character, not
2633 * as part of a multibyte character.
2635 * So it's safe to assume, but deserves a comment in the source.
2638 ***************************************************************
2639 * From: Bruno Haible <bruno@clisp.org>
2640 * To: Aharon Robbins <arnold@skeeve.com>
2641 * Subject: Re: multibyte locales: any way to find if a character isn't multibyte?
2642 * Date: Mon, 23 Jun 2003 14:27:49 +0200
2644 * On Monday 23 June 2003 14:11, you wrote:
2646 * > if (rs != '\n' && MB_CUR_MAX > 1) {
2648 * If you assume ASCII, you can even write
2650 * if (rs >= 0x30 && MB_CUR_MAX > 1) {
2652 * (this catches also the space character) but if portability to EBCDIC
2653 * systems is desired, your code is fine as is.
2657 /* Thus, the check for \n here; big speedup ! */
2658 if (rs != '\n' && gawk_mb_cur_max > 1) {
2659 int len = iop->dataend - bp;
2662 memset(&mbs, 0, sizeof(mbstate_t));
2666 if (is_valid_character(*bp))
2669 mbclen = mbrlen(bp, len, &mbs);
2671 || (mbclen == (size_t) -1)
2672 || (mbclen == (size_t) -2)
2674 /* We treat it as a singlebyte character. */
2679 } while (len > 0 && ! found);
2681 /* Check that newline found isn't the sentinel. */
2682 if (found && (bp - mbclen) < iop->dataend) {
2684 * set len to what we have so far, in case this is
2687 recm->len = bp - recm->start - mbclen;
2688 recm->rt_start = bp - mbclen;
2689 recm->rt_len = mbclen;
2694 recm->len = bp - recm->start;
2696 iop->scanoff = bp - iop->off;
2704 /* set len to what we have so far, in case this is all there is */
2705 recm->len = bp - recm->start;
2707 if (bp < iop->dataend) { /* found it in the buffer */
2708 recm->rt_start = bp;
2714 iop->scanoff = bp - iop->off;
2720 /* rsrescan --- search for a regex match in the buffer */
2723 rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
2726 size_t restart = 0, reend = 0;
2727 Regexp *RSre = RS_regexp;
2728 int regex_flags = RE_NEED_START;
2730 memset(recm, '\0', sizeof(struct recmatch));
2731 recm->start = iop->off;
2734 if (*state == INDATA)
2737 if ((iop->flag & IOP_AT_START) == 0)
2738 regex_flags |= RE_NO_BOL;
2740 /* case 1, no match */
2741 if (research(RSre, bp, 0, iop->dataend - bp, regex_flags) == -1) {
2742 /* set len, in case this all there is. */
2743 recm->len = iop->dataend - iop->off;
2747 /* ok, we matched within the buffer, set start and end */
2748 restart = RESTART(RSre, iop->off);
2749 reend = REEND(RSre, iop->off);
2751 /* case 2, null regex match, grow buffer, try again */
2752 if (restart == reend) {
2754 iop->scanoff = reend + 1;
2756 * If still room in buffer, skip over null match
2757 * and restart search. Otherwise, return.
2759 if (bp + iop->scanoff < iop->dataend) {
2763 recm->len = (bp - iop->off) + restart;
2768 * At this point, we have a non-empty match.
2770 * First, fill in rest of data. The rest of the cases return
2771 * a record and terminator.
2773 recm->len = restart;
2774 recm->rt_start = bp + restart;
2775 recm->rt_len = reend - restart;
2779 * 3. Match exactly at end:
2780 * if re is a simple string match
2781 * found a simple string match at end, return REC_OK
2783 * grow buffer, add more data, try again
2786 if (iop->off + reend >= iop->dataend) {
2787 if (reisstring(RS->stptr, RS->stlen, RSre, iop->off))
2794 * 4. Match within xxx bytes of end & maybe islong re:
2795 * return TERMNEAREND
2799 * case 4, match succeeded, but there may be more in
2800 * the next input buffer.
2802 * Consider an RS of xyz(abc)? where the
2803 * exact end of the buffer is xyza and the
2804 * next two, unread, characters are bc.
2806 * This matches the "xyz" and ends up putting the
2807 * "abc" into the front of the next record. Ooops.
2809 * The remaybelong() function looks to see if the
2810 * regex contains one of: + * ? |. This is a very
2811 * simple heuristic, but in combination with the
2812 * "end of match within a few bytes of end of buffer"
2813 * check, should keep things reasonable.
2817 * XXX: The reisstring and remaybelong tests should
2818 * really be done once when RS is assigned to and
2819 * then tested as flags here. Maybe one day.
2822 /* succession of tests is easier to trace in GDB. */
2823 if (remaybelong(RS->stptr, RS->stlen)) {
2824 char *matchend = iop->off + reend;
2826 if (iop->dataend - matchend < RS->stlen)
2834 /* rsnullscan --- handle RS = "" */
2837 rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
2841 if (*state == NOSTATE || *state == INLEADER)
2842 memset(recm, '\0', sizeof(struct recmatch));
2844 recm->start = iop->off;
2847 if (*state != NOSTATE)
2851 *(iop->dataend) = '\n';
2853 if (*state == INTERM)
2854 goto find_longest_terminator;
2855 else if (*state == INDATA)
2858 fall into things from beginning,
2859 either NOSTATE or INLEADER */
2862 /* leading newlines are ignored */
2863 while (*bp == '\n' && bp < iop->dataend)
2866 if (bp >= iop->dataend) { /* LOTS of leading newlines, sheesh. */
2868 iop->scanoff = bp - iop->off;
2872 iop->off = recm->start = bp; /* real start of record */
2874 while (*bp++ != '\n')
2877 if (bp >= iop->dataend) { /* no full terminator */
2878 iop->scanoff = recm->len = bp - iop->off - 1;
2879 if (bp == iop->dataend) { /* half a terminator */
2880 recm->rt_start = bp - 1;
2887 /* found one newline before end of buffer, check next char */
2891 /* we've now seen at least two newlines */
2893 recm->len = bp - iop->off - 1;
2894 recm->rt_start = bp - 1;
2896 find_longest_terminator:
2897 /* find as many newlines as we can, to set RT */
2898 while (*bp == '\n' && bp < iop->dataend)
2901 recm->rt_len = bp - recm->rt_start;
2902 iop->scanoff = bp - iop->off;
2904 if (bp >= iop->dataend)
2911 /* get_a_record --- read a record from IOP into out, return length of EOF, set RT */
2914 get_a_record(char **out, /* pointer to pointer to data */
2915 IOBUF *iop, /* input IOP */
2916 int *errcode) /* pointer to error variable */
2918 struct recmatch recm;
2923 static RECVALUE (*lastmatchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = NULL;
2925 if (at_eof(iop) && no_data_left(iop))
2928 if (iop->get_record != NULL)
2929 return (*iop->get_record)(out, iop, errcode);
2931 /* <fill initial buffer>= */
2932 if (has_no_data(iop) || no_data_left(iop)) {
2933 iop->count = read(iop->fd, iop->buf, iop->readsize);
2934 if (iop->count == 0) {
2935 iop->flag |= IOP_AT_EOF;
2937 } else if (iop->count == -1) {
2938 iop->flag |= IOP_AT_EOF;
2939 if (errcode != NULL)
2943 iop->dataend = iop->buf + iop->count;
2944 iop->off = iop->buf;
2948 /* <loop through file to find a record>= */
2953 ret = (*matchrec)(iop, & recm, & state);
2954 iop->flag &= ~IOP_AT_START;
2958 /* need to add more data to buffer */
2959 /* <shift data down in buffer>= */
2960 dataend_off = iop->dataend - iop->off;
2961 memmove(iop->buf, iop->off, dataend_off);
2962 iop->off = iop->buf;
2963 iop->dataend = iop->buf + dataend_off;
2965 /* <adjust recm contents>= */
2966 recm.start = iop->off;
2967 if (recm.rt_start != NULL)
2968 recm.rt_start = iop->off + recm.len;
2970 /* <read more data, break if EOF>= */
2972 #define min(x, y) (x < y ? x : y)
2973 /* subtract one in read count to leave room for sentinel */
2974 size_t room_left = iop->end - iop->dataend - 1;
2975 size_t amt_to_read = min(iop->readsize, room_left);
2977 if (amt_to_read < iop->readsize) {
2978 grow_iop_buffer(iop);
2979 /* <adjust recm contents>= */
2980 recm.start = iop->off;
2981 if (recm.rt_start != NULL)
2982 recm.rt_start = iop->off + recm.len;
2984 /* recalculate amt_to_read */
2985 room_left = iop->end - iop->dataend - 1;
2986 amt_to_read = min(iop->readsize, room_left);
2988 while (amt_to_read + iop->readsize < room_left)
2989 amt_to_read += iop->readsize;
2993 * POSIX limits read to SSIZE_MAX. There are (bizarre)
2994 * systems where this amount is small.
2996 amt_to_read = min(amt_to_read, SSIZE_MAX);
2999 iop->count = read(iop->fd, iop->dataend, amt_to_read);
3000 if (iop->count == -1) {
3002 iop->flag |= IOP_AT_EOF;
3004 } else if (iop->count == 0) {
3006 * hit EOF before matching RS, so end
3007 * the record and set RT to ""
3009 iop->flag |= IOP_AT_EOF;
3012 iop->dataend += iop->count;
3016 /* <set record, RT, return right value>= */
3019 * rtval is not a static pointer to avoid dangling pointer problems
3020 * in case awk code assigns to RT. A remote possibility, to be sure,
3021 * but Bitter Experience teaches us not to make ``that'll never
3022 * happen'' kinds of assumptions.
3024 rtval = RT_node->var_value;
3026 if (recm.rt_len == 0) {
3028 lastmatchrec = NULL;
3030 assert(recm.rt_start != NULL);
3032 * Optimization. For rs1 case, don't set RT if
3033 * character is same as last time. This knocks a
3034 * chunk of time off something simple like
3036 * gawk '{ print }' /some/big/file
3038 * Similarly, for rsnull case, if length of new RT is
3039 * shorter than current RT, just bump length down in RT.
3041 * Make sure that matchrec didn't change since the last
3042 * check. (Ugh, details, details, details.)
3044 if (lastmatchrec == NULL || lastmatchrec != matchrec) {
3045 lastmatchrec = matchrec;
3046 set_RT(recm.rt_start, recm.rt_len);
3047 } else if (matchrec == rs1scan) {
3048 if (rtval->stlen != 1 || rtval->stptr[0] != recm.rt_start[0])
3049 set_RT(recm.rt_start, recm.rt_len);
3052 } else if (matchrec == rsnullscan) {
3053 if (rtval->stlen >= recm.rt_len) {
3054 rtval->stlen = recm.rt_len;
3057 set_RT(recm.rt_start, recm.rt_len);
3059 set_RT(recm.rt_start, recm.rt_len);
3062 if (recm.len == 0) {
3066 assert(recm.start != NULL);
3071 iop->off += recm.len + recm.rt_len;
3073 if (recm.len == 0 && recm.rt_len == 0 && at_eof(iop))
3079 /* set_RS --- update things as appropriate when RS is set */
3084 static NODE *save_rs = NULL;
3087 * Don't use cmp_nodes(), which pays attention to IGNORECASE.
3090 && RS_node->var_value->stlen == save_rs->stlen
3091 && memcmp(RS_node->var_value->stptr, save_rs->stptr, save_rs->stlen) == 0) {
3093 * It could be that just IGNORECASE changed. If so,
3094 * update the regex and then do the same for FS.
3095 * set_IGNORECASE() relies on this routine to call
3098 RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case);
3102 save_rs = dupnode(RS_node->var_value);
3104 RS = force_string(RS_node->var_value);
3106 * used to be if (RS_regexp != NULL) { refree(..); refree(..); ...; }.
3107 * Please do not remerge the if condition; hinders memory deallocation
3108 * in case of fatal error in make_regexp.
3110 refree(RS_re_yes_case); /* NULL argument is ok */
3111 refree(RS_re_no_case);
3112 RS_re_yes_case = RS_re_no_case = RS_regexp = NULL;
3114 if (RS->stlen == 0) {
3116 matchrec = rsnullscan;
3117 } else if (RS->stlen > 1) {
3118 static short warned = FALSE;
3120 RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, FALSE, TRUE, TRUE);
3121 RS_re_no_case = make_regexp(RS->stptr, RS->stlen, TRUE, TRUE, TRUE);
3122 RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case);
3124 matchrec = rsrescan;
3126 if (do_lint && ! warned) {
3127 lintwarn(_("multicharacter value of `RS' is a gawk extension"));
3133 if (current_field_sep() == Using_FS)
3137 /* pty_vs_pipe --- return true if should use pty instead of pipes for `|&' */
3140 * This works by checking if PROCINFO["command", "pty"] exists and is true.
3144 pty_vs_pipe(const char *command)
3146 #ifdef HAVE_TERMIOS_H
3152 if (PROCINFO_node == NULL)
3155 full_len = strlen(command)
3156 + SUBSEP_node->var_value->stlen
3157 + 3 /* strlen("pty") */
3158 + 1; /* string terminator */
3159 emalloc(full_index, char *, full_len, "pty_vs_pipe");
3160 sprintf(full_index, "%s%.*spty", command,
3161 (int) SUBSEP_node->var_value->stlen, SUBSEP_node->var_value->stptr);
3163 sub = make_string(full_index, strlen(full_index));
3164 val = in_array(PROCINFO_node, sub);
3169 if (val->flags & MAYBE_NUM)
3170 (void) force_number(val);
3171 if (val->flags & NUMBER)
3172 return (val->numbr != 0.0);
3174 return (val->stlen != 0);
3176 #endif /* HAVE_TERMIOS_H */
3180 /* iopflags2str --- make IOP flags printable */
3183 iopflags2str(int flag)
3185 static const struct flagtab values[] = {
3186 { IOP_IS_TTY, "IOP_IS_TTY" },
3187 { IOP_NOFREE_OBJ, "IOP_NOFREE_OBJ" },
3188 { IOP_AT_EOF, "IOP_AT_EOF" },
3189 { IOP_CLOSED, "IOP_CLOSED" },
3190 { IOP_AT_START, "IOP_AT_START" },
3194 return genflags2str(flag, values);
3197 /* free_rp --- release the memory used by rp */
3200 free_rp(struct redirect *rp)
3206 /* inetfile --- return true for a /inet special file, set other values */
3209 inetfile(const char *str, int *length, int *family)
3213 if (strncmp(str, "/inet/", 6) == 0) {
3218 *family = AF_UNSPEC;
3219 } else if (strncmp(str, "/inet4/", 7) == 0) {
3225 } else if (strncmp(str, "/inet6/", 7) == 0) {
3231 #ifndef HAVE_GETADDRINFO
3232 fatal(_("IPv6 communication is not supported"));