2 * io.c --- routines for dealing with input and output and records
6 * Copyright (C) 1986, 1988, 1989, 1991-2014 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)
45 #if ! defined(S_ISREG) && defined(S_IFREG)
46 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
58 #ifdef HAVE_SYS_SOCKET_H
59 #include <sys/socket.h>
62 #endif /* HAVE_SYS_SOCKET_H */
64 #ifdef HAVE_NETINET_IN_H
65 #include <netinet/in.h>
67 #ifdef HAVE_ARPA_INET_H
68 #include <arpa/inet.h>
71 #else /* ! HAVE_NETINET_IN_H */
73 #endif /* HAVE_NETINET_IN_H */
77 #endif /* HAVE_NETDB_H */
79 #ifndef HAVE_GETADDRINFO
80 #include "missing_d/getaddrinfo.h"
83 #ifndef AI_ADDRCONFIG /* not everyone has this symbol */
84 #define AI_ADDRCONFIG 0
85 #endif /* AI_ADDRCONFIG */
87 #ifndef HAVE_SOCKADDR_STORAGE
88 #define sockaddr_storage sockaddr /* for older systems */
89 #endif /* HAVE_SOCKADDR_STORAGE */
91 #endif /* HAVE_SOCKETS */
107 #if defined(HAVE_POPEN_H)
116 #define ENFILE EMFILE
119 #if defined(__DJGPP__)
120 #define closemaybesocket(fd) close(fd)
126 #define SS$_EXBYTLM 0x2a14 /* VMS 8.4 seen */
129 #define closemaybesocket(fd) close(fd)
136 # define SHUT_RD SD_RECEIVE
144 # define SHUT_WR SD_SEND
152 # define SHUT_RDWR SD_BOTH
158 /* MinGW defines non-trivial macros on pc/socket.h. */
160 # define FD_TO_SOCKET(fd) (fd)
161 # define closemaybesocket(fd) close(fd)
165 # define SOCKET_TO_FD(s) (s)
169 #endif /* HAVE_SOCKETS */
172 #define setsid() /* nothing */
173 #endif /* HAVE_SETSID */
175 #if defined(GAWK_AIX)
176 #undef TANDEM /* AIX defines this in one of its header files */
180 #define PIPES_SIMULATED
184 # ifndef PIPES_SIMULATED
185 # define pipe(fds) _pipe(fds, 0, O_NOINHERIT)
190 /* increment NR or FNR */
191 #define INCREMENT_REC(X) (do_mpfr && X == (LONG_MAX - 1)) ? \
192 (mpz_add_ui(M##X, M##X, 1), X = 0) : X++
194 #define INCREMENT_REC(X) X++
197 typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
199 /* Several macros to make the code a bit clearer. */
200 #define at_eof(iop) (((iop)->flag & IOP_AT_EOF) != 0)
201 #define has_no_data(iop) ((iop)->dataend == NULL)
202 #define no_data_left(iop) ((iop)->off >= (iop)->dataend)
205 * The key point to the design is to split out the code that searches through
206 * a buffer looking for the record and the terminator into separate routines,
207 * with a higher-level routine doing the reading of data and buffer management.
208 * This makes the code easier to manage; the buffering code is the same
209 * independent of how we find a record. Communication is via the return
213 typedef enum recvalues {
214 REC_OK, /* record and terminator found, recmatch struct filled in */
215 NOTERM, /* no terminator found, give me more input data */
216 TERMATEND, /* found terminator at end of buffer */
217 TERMNEAREND /* found terminator close to end of buffer, for when
218 the RE might be match more data further in
223 * Between calls to a scanning routine, the state is stored in
224 * an enum scanstate variable. Not all states apply to all
225 * variants, but the higher code doesn't really care.
228 typedef enum scanstate {
229 NOSTATE, /* scanning not started yet (all) */
230 INLEADER, /* skipping leading data (RS = "") */
231 INDATA, /* in body of record (all) */
232 INTERM /* scanning terminator (RS = "", RS = regexp) */
236 * When a record is seen (REC_OK or TERMATEND), the following
237 * structure is filled in.
241 char *start; /* record start */
242 size_t len; /* length of record */
243 char *rt_start; /* start of terminator */
244 size_t rt_len; /* length of terminator */
248 static int iop_close(IOBUF *iop);
249 struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg);
250 static void close_one(void);
251 static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how);
252 #ifndef PIPES_SIMULATED
253 static int wait_any(int interesting);
255 static IOBUF *gawk_popen(const char *cmd, struct redirect *rp);
256 static IOBUF *iop_alloc(int fd, const char *name, int errno_val);
257 static IOBUF *iop_finish(IOBUF *iop);
258 static int gawk_pclose(struct redirect *rp);
259 static int str2mode(const char *mode);
260 static int two_way_open(const char *str, struct redirect *rp);
261 static int pty_vs_pipe(const char *command);
262 static void find_input_parser(IOBUF *iop);
263 static bool find_output_wrapper(awk_output_buf_t *outbuf);
264 static void init_output_wrapper(awk_output_buf_t *outbuf);
265 static bool find_two_way_processor(const char *name, struct redirect *rp);
267 static RECVALUE rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
268 static RECVALUE rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
269 static RECVALUE rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
271 static RECVALUE (*matchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = rs1scan;
273 static int get_a_record(char **out, IOBUF *iop, int *errcode);
275 static void free_rp(struct redirect *rp);
276 static int inetfile(const char *str, int *length, int *family);
278 static NODE *in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx);
279 static long get_read_timeout(IOBUF *iop);
280 static ssize_t read_with_timeout(int fd, char *buf, size_t size);
282 static bool read_can_timeout = false;
283 static long read_timeout;
284 static long read_default_timeout;
286 static struct redirect *red_head = NULL;
287 static NODE *RS = NULL;
288 static Regexp *RS_re_yes_case; /* regexp for RS when ignoring case */
289 static Regexp *RS_re_no_case; /* regexp for RS when not ignoring case */
290 static Regexp *RS_regexp;
294 extern NODE *ARGC_node;
295 extern NODE *ARGV_node;
296 extern NODE *ARGIND_node;
297 extern NODE **fields_arr;
299 /* init_io --- set up timeout related variables */
306 /* Only MinGW has a non-trivial implementation of this. */
310 * N.B.: all these hacks are to minimize the effect
311 * on programs that do not care about timeout.
314 /* Parse the env. variable only once */
315 tmout = getenv_long("GAWK_READ_TIMEOUT");
317 read_default_timeout = tmout;
318 read_can_timeout = true;
322 * PROCINFO entries for timeout are dynamic;
323 * We can't be any more specific than this.
325 if (PROCINFO_node != NULL)
326 read_can_timeout = true;
330 #if defined(__DJGPP__) || defined(__MINGW32__) || defined(__EMX__) || defined(__CYGWIN__)
331 /* binmode --- convert BINMODE to string for fopen */
334 binmode(const char *mode)
338 if ((BINMODE & BINMODE_INPUT) != 0)
343 if ((BINMODE & BINMODE_OUTPUT) != 0)
344 mode = (mode[0] == 'w' ? "wb" : "ab");
350 #define binmode(mode) (mode)
354 /* File pointers have an extra level of indirection, and there are cases where
355 `stdin' can be null. That can crash gawk if fileno() is used as-is. */
356 static int vmsrtl_fileno(FILE *);
357 static int vmsrtl_fileno(fp) FILE *fp; { return fileno(fp); }
359 #define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1)
362 /* after_beginfile --- reset necessary state after BEGINFILE has run */
365 after_beginfile(IOBUF **curfile)
373 * Input parsers could have been changed by BEGINFILE,
374 * so delay check until now.
377 find_input_parser(iop);
384 fname = iop->public.name;
385 errcode = iop->errcode;
388 update_ERRNO_int(errcode);
391 if (! valid && errcode == EISDIR && ! do_traditional) {
392 warning(_("command line argument `%s' is a directory: skipped"), fname);
393 return; /* read next file */
395 fatal(_("cannot open file `%s' for reading (%s)"),
396 fname, strerror(errcode));
400 /* nextfile --- move to the next input data file */
402 * Return value > 0 ----> run BEGINFILE block
403 * *curfile = NULL ----> hit EOF, run ENDFILE block
407 nextfile(IOBUF **curfile, bool skipping)
410 static bool files = false;
413 int fd = INVALID_HANDLE;
415 IOBUF *iop = *curfile;
418 if (skipping) { /* for 'nextfile' call */
421 errcode = iop->errcode;
422 (void) iop_close(iop);
425 return (errcode == 0);
430 assert(iop->public.fd != INVALID_HANDLE);
431 (void) iop_close(iop);
433 return 1; /* run endfile block */
438 argc = get_number_si(ARGC_node->var_value);
440 for (; i < argc; i++) {
441 tmp = make_number((AWKNUM) i);
442 (void) force_string(tmp);
443 arg = in_array(ARGV_node, tmp);
445 if (arg == NULL || arg->stlen == 0)
447 arg = force_string(arg);
448 arg->stptr[arg->stlen] = '\0';
449 if (! do_traditional) {
450 unref(ARGIND_node->var_value);
451 ARGIND_node->var_value = make_number((AWKNUM) i);
454 if (! arg_assign(arg->stptr, false)) {
458 /* manage the awk variables: */
459 unref(FILENAME_node->var_value);
460 FILENAME_node->var_value = dupnode(arg);
462 if (is_mpg_number(FNR_node->var_value))
467 /* IOBUF management: */
469 fd = devopen(fname, binmode("r"));
470 if (fd == INVALID_HANDLE && errno == EMFILE) {
473 fd = devopen(fname, binmode("r"));
476 if (! do_traditional)
477 update_ERRNO_int(errno);
478 iop = iop_alloc(fd, fname, errcode);
479 *curfile = iop_finish(iop);
480 if (iop->public.fd == INVALID_HANDLE)
481 iop->errcode = errcode;
485 if (! do_traditional && iop->errcode != 0)
486 update_ERRNO_int(iop->errcode);
488 return ++i; /* run beginfile block */
492 if (files == false) {
494 /* no args. -- use stdin */
495 /* FNR is init'ed to 0 */
497 if (! do_traditional)
498 update_ERRNO_int(errno);
500 unref(FILENAME_node->var_value);
501 FILENAME_node->var_value = make_string("-", 1);
502 FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */
504 iop = iop_alloc(fileno(stdin), fname, 0);
505 *curfile = iop_finish(iop);
507 if (iop->public.fd == INVALID_HANDLE) {
510 update_ERRNO_int(errno);
511 (void) iop_close(iop);
513 fatal(_("cannot open file `%s' for reading (%s)"),
514 fname, strerror(errcode));
516 return ++i; /* run beginfile block */
519 return -1; /* end of input, run end block or Op_atexit */
522 /* set_FNR --- update internal FNR from awk variable */
527 NODE *n = FNR_node->var_value;
528 (void) force_number(n);
530 if (is_mpg_number(n))
531 FNR = mpg_set_var(FNR_node);
534 FNR = get_number_si(n);
537 /* set_NR --- update internal NR from awk variable */
542 NODE *n = NR_node->var_value;
543 (void) force_number(n);
545 if (is_mpg_number(n))
546 NR = mpg_set_var(NR_node);
549 NR = get_number_si(n);
552 /* inrec --- This reads in a record from the input file */
555 inrec(IOBUF *iop, int *errcode)
561 if (at_eof(iop) && no_data_left(iop))
563 else if ((iop->flag & IOP_CLOSED) != 0)
566 cnt = get_a_record(& begin, iop, errcode);
571 update_ERRNO_int(*errcode);
575 set_record(begin, cnt);
581 /* remap_std_file --- reopen a standard descriptor on /dev/null */
584 remap_std_file(int oldfd)
590 * Give OS-specific routines in gawkmisc.c a chance to interpret
591 * "/dev/null" as appropriate for their platforms.
593 newfd = os_devopen("/dev/null", O_RDWR);
594 if (newfd == INVALID_HANDLE)
595 newfd = open("/dev/null", O_RDWR);
597 /* if oldfd is open, dup2() will close oldfd for us first. */
598 ret = dup2(newfd, oldfd);
607 /* iop_close --- close an open IOP */
610 iop_close(IOBUF *iop)
619 iop->flag &= ~IOP_AT_EOF;
620 iop->flag |= IOP_CLOSED; /* there may be dangling pointers */
623 * Closing standard files can cause crufty code elsewhere to lose.
624 * So we remap the standard file to /dev/null.
625 * Thanks to Jim Meyering for the suggestion.
627 if (iop->public.close_func != NULL)
628 iop->public.close_func(&iop->public);
630 if (iop->public.fd != INVALID_HANDLE) {
631 if (iop->public.fd == fileno(stdin)
632 || iop->public.fd == fileno(stdout)
633 || iop->public.fd == fileno(stderr))
634 ret = remap_std_file(iop->public.fd);
636 ret = closemaybesocket(iop->public.fd);
640 warning(_("close of fd %d (`%s') failed (%s)"), iop->public.fd,
641 iop->public.name, strerror(errno));
643 * Be careful -- $0 may still reference the buffer even though
644 * an explicit close is being done; in the future, maybe we
645 * can do this a bit better.
648 if ((fields_arr[0]->stptr >= iop->buf)
649 && (fields_arr[0]->stptr < (iop->buf + iop->size))) {
652 t = make_string(fields_arr[0]->stptr,
653 fields_arr[0]->stlen);
654 unref(fields_arr[0]);
657 * This used to be here:
661 * Don't do that; reset_record() throws away all fields,
662 * saves FS etc. We just need to make sure memory isn't
663 * corrupted and that references to $0 and fields work.
670 return ret == -1 ? 1 : 0;
673 /* redflags2str --- turn redirection flags into a string, for debugging */
676 redflags2str(int flags)
678 static const struct flagtab redtab[] = {
679 { RED_FILE, "RED_FILE" },
680 { RED_PIPE, "RED_PIPE" },
681 { RED_READ, "RED_READ" },
682 { RED_WRITE, "RED_WRITE" },
683 { RED_APPEND, "RED_APPEND" },
684 { RED_NOBUF, "RED_NOBUF" },
685 { RED_EOF, "RED_EOF" },
686 { RED_TWOWAY, "RED_TWOWAY" },
687 { RED_PTY, "RED_PTY" },
688 { RED_SOCKET, "RED_SOCKET" },
689 { RED_TCP, "RED_TCP" },
693 return genflags2str(flags, redtab);
696 /* redirect --- Redirection for printf and print commands */
699 redirect(NODE *redir_exp, int redirtype, int *errflg)
705 const char *direction = "to";
708 const char *what = NULL;
710 int len; /* used with /inet */
711 static struct redirect *save_rp = NULL; /* hold onto rp that should
716 fatal(_("redirection not allowed in sandbox mode"));
719 case redirect_append:
722 case redirect_output:
723 outflag = (RED_FILE|RED_WRITE);
725 if (redirtype == redirect_output)
731 tflag = (RED_PIPE|RED_WRITE);
734 case redirect_pipein:
735 tflag = (RED_PIPE|RED_READ);
739 tflag = (RED_FILE|RED_READ);
742 case redirect_twoway:
743 tflag = (RED_READ|RED_WRITE|RED_TWOWAY);
749 if (do_lint && (redir_exp->flags & STRCUR) == 0)
750 lintwarn(_("expression in `%s' redirection only has numeric value"),
752 redir_exp = force_string(redir_exp);
753 str = redir_exp->stptr;
755 if (str == NULL || *str == '\0')
756 fatal(_("expression for `%s' redirection has null string value"),
759 if (do_lint && (strncmp(str, "0", redir_exp->stlen) == 0
760 || strncmp(str, "1", redir_exp->stlen) == 0))
761 lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"),
766 * Use /inet4 to force IPv4, /inet6 to force IPv6, and plain
767 * /inet will be whatever we get back from the system.
769 if (inetfile(str, & len, NULL)) {
771 if (strncmp(str + len, "tcp/", 4) == 0)
772 tflag |= RED_TCP; /* use shutdown when closing */
774 #endif /* HAVE_SOCKETS */
776 for (rp = red_head; rp != NULL; rp = rp->next) {
777 #ifndef PIPES_SIMULATED
779 * This is an efficiency hack. We want to
780 * recover the process slot for dead children,
781 * if at all possible. Messing with signal() for
782 * SIGCLD leads to lots of headaches. However, if
783 * we've gotten EOF from a child input pipeline, it's
784 * a good bet that the child has died. So recover it.
786 if ((rp->flag & RED_EOF) != 0 && redirtype == redirect_pipein) {
789 /* MinGW cannot wait for any process. */
795 #endif /* PIPES_SIMULATED */
797 /* now check for a match */
798 if (strlen(rp->value) == redir_exp->stlen
799 && memcmp(rp->value, str, redir_exp->stlen) == 0
800 && ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag
802 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) {
804 int rpflag = (rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY));
805 int newflag = (tflag & ~(RED_NOBUF|RED_EOF|RED_PTY));
807 if (do_lint && rpflag != newflag)
809 _("unnecessary mixing of `>' and `>>' for file `%.*s'"),
810 (int) redir_exp->stlen, rp->value);
818 if (save_rp != NULL) {
822 emalloc(rp, struct redirect *, sizeof(struct redirect), "redirect");
823 emalloc(str, char *, redir_exp->stlen + 1, "redirect");
824 memcpy(str, redir_exp->stptr, redir_exp->stlen);
825 str[redir_exp->stlen] = '\0';
828 init_output_wrapper(& rp->output);
829 rp->output.name = str;
834 str = rp->value; /* get \0 terminated string */
837 while (rp->output.fp == NULL && rp->iop == NULL) {
838 if (! new_rp && (rp->flag & RED_EOF) != 0) {
840 * Encountered EOF on file or pipe -- must be cleared
841 * by explicit close() before reading more
849 case redirect_output:
851 if ((rp->flag & RED_USED) != 0)
852 mode = (rp->mode[1] == 'b') ? "ab" : "a";
854 case redirect_append:
858 /* synchronize output before new pipe */
861 os_restore_mode(fileno(stdin));
862 if ((rp->output.fp = popen(str, binmode("w"))) == NULL)
863 fatal(_("can't open pipe `%s' for output (%s)"),
864 str, strerror(errno));
866 /* set close-on-exec */
867 os_close_on_exec(fileno(rp->output.fp), str, "pipe", "to");
868 rp->flag |= RED_NOBUF;
870 case redirect_pipein:
872 if (gawk_popen(str, rp) == NULL)
873 fatal(_("can't open pipe `%s' for input (%s)"),
874 str, strerror(errno));
878 fd = devopen(str, binmode("r"));
879 if (fd == INVALID_HANDLE && errno == EISDIR) {
881 /* do not free rp, saving it for reuse (save_rp = rp) */
884 rp->iop = iop_alloc(fd, str, errno);
885 find_input_parser(rp->iop);
887 if (! rp->iop->valid) {
888 if (! do_traditional && rp->iop->errcode != 0)
889 update_ERRNO_int(rp->iop->errcode);
894 case redirect_twoway:
895 direction = "to/from";
896 if (! two_way_open(str, rp)) {
898 if (inetfile(str, NULL, NULL)) {
900 /* do not free rp, saving it for reuse (save_rp = rp) */
904 fatal(_("can't open two way pipe `%s' for input/output (%s)"),
905 str, strerror(errno));
914 rp->output.mode = mode;
915 fd = devopen(str, mode);
917 if (fd > INVALID_HANDLE) {
918 if (fd == fileno(stdin))
919 rp->output.fp = stdin;
920 else if (fd == fileno(stdout))
921 rp->output.fp = stdout;
922 else if (fd == fileno(stderr))
923 rp->output.fp = stderr;
925 const char *omode = mode;
926 #if defined(F_GETFL) && defined(O_APPEND)
929 fd_flags = fcntl(fd, F_GETFL);
930 if (fd_flags != -1 && (fd_flags & O_APPEND) == O_APPEND)
931 omode = binmode("a");
933 os_close_on_exec(fd, str, "file", "");
934 rp->output.fp = fdopen(fd, (const char *) omode);
935 rp->mode = (const char *) mode;
936 /* don't leak file descriptors */
937 if (rp->output.fp == NULL)
940 if (rp->output.fp != NULL && os_isatty(fd))
941 rp->flag |= RED_NOBUF;
943 /* Move rp to the head of the list. */
944 if (! new_rp && red_head != rp) {
945 if ((rp->prev->next = rp->next) != NULL)
946 rp->next->prev = rp->prev;
953 find_output_wrapper(& rp->output);
956 if (rp->output.fp == NULL && rp->iop == NULL) {
957 /* too many files open -- close one and try again */
958 if (errno == EMFILE || errno == ENFILE)
961 /* Alpha/VMS V7.1+ C RTL is returning these instead
962 of EMFILE (haven't tried other post-V6.2 systems) */
963 else if ((errno == EIO || errno == EVMSERR) &&
964 (vaxc$errno == SS$_EXQUOTA ||
965 vaxc$errno == SS$_EXBYTLM ||
966 vaxc$errno == RMS$_ACC ||
967 vaxc$errno == RMS$_SYN))
972 * Some other reason for failure.
974 * On redirection of input from a file,
975 * just return an error, so e.g. getline
976 * can return -1. For output to file,
977 * complain. The shell will complain on
978 * a bad command to a pipe.
982 if ( redirtype == redirect_output
983 || redirtype == redirect_append) {
984 /* multiple messages make life easier for translators */
985 if (*direction == 'f')
986 fatal(_("can't redirect from `%s' (%s)"),
987 str, strerror(errno));
989 fatal(_("can't redirect to `%s' (%s)"),
990 str, strerror(errno));
992 /* do not free rp, saving it for reuse (save_rp = rp) */
1001 * It opened successfully, hook it into the list.
1002 * Maintain the list in most-recently-used first order.
1004 if (red_head != NULL)
1005 red_head->prev = rp;
1007 rp->next = red_head;
1014 /* getredirect --- find the struct redirect for this file or pipe */
1017 getredirect(const char *str, int len)
1019 struct redirect *rp;
1021 for (rp = red_head; rp != NULL; rp = rp->next)
1022 if (strlen(rp->value) == len && memcmp(rp->value, str, len) == 0)
1028 /* close_one --- temporarily close an open file to re-use the fd */
1033 struct redirect *rp;
1034 struct redirect *rplast = NULL;
1036 static bool warned = false;
1038 if (do_lint && ! warned) {
1040 lintwarn(_("reached system limit for open files: starting to multiplex file descriptors"));
1043 /* go to end of list first, to pick up least recently used entry */
1044 for (rp = red_head; rp != NULL; rp = rp->next)
1046 /* now work back up through the list */
1047 for (rp = rplast; rp != NULL; rp = rp->prev) {
1048 /* don't close standard files! */
1049 if (rp->output.fp == NULL || rp->output.fp == stderr || rp->output.fp == stdout)
1052 if ((rp->flag & (RED_FILE|RED_WRITE)) == (RED_FILE|RED_WRITE)) {
1053 rp->flag |= RED_USED;
1055 if (rp->output.gawk_fclose(rp->output.fp, rp->output.opaque) != 0)
1056 warning(_("close of `%s' failed (%s)."),
1057 rp->value, strerror(errno));
1058 rp->output.fp = NULL;
1063 /* surely this is the only reason ??? */
1064 fatal(_("too many pipes or input files open"));
1067 /* do_close --- completely close an open file or pipe */
1073 struct redirect *rp;
1074 two_way_close_type how = CLOSE_ALL; /* default */
1077 /* 2nd arg if present: "to" or "from" for two-way pipe */
1078 /* DO NOT use _() on the strings here! */
1079 tmp2 = POP_STRING();
1080 if (strcasecmp(tmp2->stptr, "to") == 0)
1082 else if (strcasecmp(tmp2->stptr, "from") == 0)
1086 fatal(_("close: second argument must be `to' or `from'"));
1091 tmp = POP_STRING(); /* 1st arg: redir to close */
1093 for (rp = red_head; rp != NULL; rp = rp->next) {
1094 if (strlen(rp->value) == tmp->stlen
1095 && memcmp(rp->value, tmp->stptr, tmp->stlen) == 0)
1099 if (rp == NULL) { /* no match, return -1 */
1103 lintwarn(_("close: `%.*s' is not an open file, pipe or co-process"),
1104 (int) tmp->stlen, tmp->stptr);
1106 if (! do_traditional) {
1107 /* update ERRNO manually, using errno = ENOENT is a stretch. */
1108 cp = _("close of redirection that was never opened");
1109 update_ERRNO_string(cp);
1113 return make_number((AWKNUM) -1.0);
1116 fflush(stdout); /* synchronize regular output */
1117 tmp = make_number((AWKNUM) close_redir(rp, false, how));
1120 * POSIX says close() returns 0 on success, non-zero otherwise.
1121 * For POSIX, at this point we just return 0. Otherwise we
1122 * return the exit status of the process or of pclose(), depending.
1123 * This whole business is a mess.
1127 tmp = make_number((AWKNUM) 0);
1132 /* close_rp --- separate function to just do closing */
1135 close_rp(struct redirect *rp, two_way_close_type how)
1140 if ((rp->flag & RED_TWOWAY) != 0) { /* two-way pipe */
1142 if ((how == CLOSE_ALL || how == CLOSE_TO) && rp->output.fp != NULL) {
1144 if ((rp->flag & RED_TCP) != 0)
1145 (void) shutdown(fileno(rp->output.fp), SHUT_WR);
1146 #endif /* HAVE_SOCKETS */
1148 if ((rp->flag & RED_PTY) != 0) {
1149 rp->output.gawk_fwrite("\004\n", sizeof("\004\n") - 1, 1, rp->output.fp, rp->output.opaque);
1150 rp->output.gawk_fflush(rp->output.fp, rp->output.opaque);
1152 status = rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1153 rp->output.fp = NULL;
1157 if (how == CLOSE_ALL || how == CLOSE_FROM) {
1158 if ((rp->flag & RED_SOCKET) != 0 && rp->iop != NULL) {
1160 if ((rp->flag & RED_TCP) != 0)
1161 (void) shutdown(rp->iop->public.fd, SHUT_RD);
1162 #endif /* HAVE_SOCKETS */
1163 (void) iop_close(rp->iop);
1165 status = gawk_pclose(rp);
1169 } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) {
1171 status = pclose(rp->output.fp);
1172 if ((BINMODE & BINMODE_INPUT) != 0)
1173 os_setbinmode(fileno(stdin), O_BINARY);
1175 rp->output.fp = NULL;
1176 } else if (rp->output.fp != NULL) { /* write to file */
1177 status = rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1178 rp->output.fp = NULL;
1179 } else if (rp->iop != NULL) { /* read from pipe/file */
1180 if ((rp->flag & RED_PIPE) != 0) /* read from pipe */
1181 status = gawk_pclose(rp);
1182 /* gawk_pclose sets rp->iop to null */
1183 else { /* read from file */
1184 status = iop_close(rp->iop);
1192 /* close_redir --- close an open file or pipe */
1195 close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how)
1201 if (rp->output.fp == stdout || rp->output.fp == stderr)
1202 goto checkwarn; /* bypass closing, remove from list */
1204 if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL)
1205 lintwarn(_("close: redirection `%s' not opened with `|&', second argument ignored"),
1208 status = close_rp(rp, how);
1211 int save_errno = errno;
1212 char *s = strerror(save_errno);
1215 * BWK's awk, as far back as SVR4 (1989) would check
1216 * and warn about the status of close. However, when
1217 * we did this we got too many complaints, so we moved
1218 * it to be under lint control.
1221 if ((rp->flag & RED_PIPE) != 0)
1222 lintwarn(_("failure status (%d) on pipe close of `%s' (%s)"),
1223 status, rp->value, s);
1225 lintwarn(_("failure status (%d) on file close of `%s' (%s)"),
1226 status, rp->value, s);
1229 if (! do_traditional) {
1230 /* set ERRNO too so that program can get at it */
1231 update_ERRNO_int(save_errno);
1238 * Don't use lintwarn() here. If lint warnings are fatal,
1239 * doing so prevents us from closing other open redirections.
1241 * Using multiple full messages instead of string parameters
1242 * for the types makes message translation easier.
1244 if ((rp->flag & RED_SOCKET) != 0)
1245 warning(_("no explicit close of socket `%s' provided"),
1247 else if ((rp->flag & RED_TWOWAY) != 0)
1248 warning(_("no explicit close of co-process `%s' provided"),
1250 else if ((rp->flag & RED_PIPE) != 0)
1251 warning(_("no explicit close of pipe `%s' provided"),
1254 warning(_("no explicit close of file `%s' provided"),
1258 /* remove it from the list if closing both or both ends have been closed */
1259 if (how == CLOSE_ALL || (rp->iop == NULL && rp->output.fp == NULL)) {
1260 if (rp->next != NULL)
1261 rp->next->prev = rp->prev;
1262 if (rp->prev != NULL)
1263 rp->prev->next = rp->next;
1265 red_head = rp->next;
1272 /* flush_io --- flush all open output files */
1277 struct redirect *rp;
1281 /* we don't warn about stdout/stderr if EPIPE, but we do error exit */
1282 if (fflush(stdout)) {
1284 warning(_("error writing standard output (%s)"), strerror(errno));
1287 if (fflush(stderr)) {
1289 warning(_("error writing standard error (%s)"), strerror(errno));
1292 for (rp = red_head; rp != NULL; rp = rp->next)
1293 /* flush both files and pipes, what the heck */
1294 if ((rp->flag & RED_WRITE) != 0 && rp->output.fp != NULL) {
1295 if (rp->output.gawk_fflush(rp->output.fp, rp->output.opaque)) {
1296 if ((rp->flag & RED_PIPE) != 0)
1297 warning(_("pipe flush of `%s' failed (%s)."),
1298 rp->value, strerror(errno));
1299 else if ((rp->flag & RED_TWOWAY) != 0)
1300 warning(_("co-process flush of pipe to `%s' failed (%s)."),
1301 rp->value, strerror(errno));
1303 warning(_("file flush of `%s' failed (%s)."),
1304 rp->value, strerror(errno));
1309 status = -1; /* canonicalize it */
1313 /* close_io --- close all open files, called when exiting */
1316 close_io(bool *stdio_problem)
1318 struct redirect *rp;
1319 struct redirect *next;
1323 for (rp = red_head; rp != NULL; rp = next) {
1326 * close_redir() will print a message if needed.
1327 * if do_lint, warn about lack of explicit close
1329 if (close_redir(rp, do_lint, CLOSE_ALL))
1334 * Some of the non-Unix os's have problems doing an fclose()
1335 * on stdout and stderr. Since we don't really need to close
1336 * them, we just flush them, and do that across the board.
1338 *stdio_problem = false;
1339 /* we don't warn about stdout/stderr if EPIPE, but we do error exit */
1340 if (fflush(stdout) != 0) {
1342 warning(_("error writing standard output (%s)"), strerror(errno));
1344 *stdio_problem = true;
1346 if (fflush(stderr) != 0) {
1348 warning(_("error writing standard error (%s)"), strerror(errno));
1350 *stdio_problem = true;
1355 /* str2mode --- convert a string mode to an integer mode */
1358 str2mode(const char *mode)
1361 const char *second = & mode[1];
1369 if (*second == '+' || *second == 'w')
1374 ret = O_WRONLY|O_CREAT|O_TRUNC;
1375 if (*second == '+' || *second == 'r')
1376 ret = O_RDWR|O_CREAT|O_TRUNC;
1380 ret = O_WRONLY|O_APPEND|O_CREAT;
1382 ret = O_RDWR|O_APPEND|O_CREAT;
1389 if (strchr(mode, 'b') != NULL)
1396 /* socketopen --- open a socket and set it into connected state */
1399 socketopen(int family, int type, const char *localpname,
1400 const char *remotepname, const char *remotehostname)
1402 struct addrinfo *lres, *lres0;
1403 struct addrinfo lhints;
1404 struct addrinfo *rres, *rres0;
1405 struct addrinfo rhints;
1409 int socket_fd = INVALID_HANDLE;
1410 int any_remote_host = (strcmp(remotehostname, "0") == 0);
1412 memset(& lhints, '\0', sizeof (lhints));
1413 lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
1414 lhints.ai_socktype = type;
1415 lhints.ai_family = family;
1417 lerror = getaddrinfo(NULL, localpname, & lhints, & lres);
1419 if (strcmp(localpname, "0") != 0)
1420 fatal(_("local port %s invalid in `/inet'"), localpname);
1426 while (lres != NULL) {
1427 memset (& rhints, '\0', sizeof (rhints));
1428 rhints.ai_flags = lhints.ai_flags;
1429 rhints.ai_socktype = lhints.ai_socktype;
1430 rhints.ai_family = lhints.ai_family;
1431 rhints.ai_protocol = lhints.ai_protocol;
1433 rerror = getaddrinfo(any_remote_host ? NULL : remotehostname,
1434 remotepname, & rhints, & rres);
1437 freeaddrinfo(lres0);
1438 fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname);
1441 socket_fd = INVALID_HANDLE;
1442 while (rres != NULL) {
1443 socket_fd = socket(rres->ai_family,
1444 rres->ai_socktype, rres->ai_protocol);
1445 if (socket_fd < 0 || socket_fd == INVALID_HANDLE)
1448 if (type == SOCK_STREAM) {
1451 struct linger linger;
1452 memset(& linger, '\0', sizeof(linger));
1454 setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
1455 (char *) & on, sizeof(on));
1458 /* linger for 30/100 second */
1459 linger.l_linger = 30;
1460 setsockopt(socket_fd, SOL_SOCKET, SO_LINGER,
1461 (char *) & linger, sizeof(linger));
1464 if (bind(socket_fd, lres->ai_addr, lres->ai_addrlen) != 0)
1467 if (! any_remote_host) { /* not ANY => create a client */
1468 if (connect(socket_fd, rres->ai_addr, rres->ai_addrlen) == 0)
1470 } else { /* remote host is ANY => create a server */
1471 if (type == SOCK_STREAM) {
1472 int clientsocket_fd = INVALID_HANDLE;
1474 struct sockaddr_storage remote_addr;
1475 socklen_t namelen = sizeof(remote_addr);
1477 if (listen(socket_fd, 1) >= 0
1478 && (clientsocket_fd = accept(socket_fd,
1479 (struct sockaddr *) & remote_addr,
1481 closemaybesocket(socket_fd);
1482 socket_fd = clientsocket_fd;
1485 } else if (type == SOCK_DGRAM) {
1488 struct sockaddr_storage remote_addr;
1489 socklen_t read_len = 0;
1491 if (recvfrom(socket_fd, buf, 1, MSG_PEEK,
1492 (struct sockaddr *) & remote_addr,
1495 && connect(socket_fd,
1496 (struct sockaddr *) & remote_addr,
1504 if (socket_fd != INVALID_HANDLE)
1505 closemaybesocket(socket_fd);
1506 socket_fd = INVALID_HANDLE;
1507 rres = rres->ai_next;
1509 freeaddrinfo(rres0);
1510 if (socket_fd != INVALID_HANDLE)
1512 lres = lres->ai_next;
1515 freeaddrinfo(lres0);
1519 #endif /* HAVE_SOCKETS */
1521 /* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
1524 * Strictly speaking, "name" is not a "const char *" because we temporarily
1525 * change the string.
1529 devopen(const char *name, const char *mode)
1538 if (strcmp(name, "-") == 0)
1539 return fileno(stdin);
1541 flag = str2mode(mode);
1542 openfd = INVALID_HANDLE;
1547 if ((openfd = os_devopen(name, flag)) != INVALID_HANDLE) {
1548 os_close_on_exec(openfd, name, "file", "");
1552 if (strncmp(name, "/dev/", 5) == 0) {
1553 cp = (char *) name + 5;
1555 if (strcmp(cp, "stdin") == 0 && (flag & O_ACCMODE) == O_RDONLY)
1556 openfd = fileno(stdin);
1557 else if (strcmp(cp, "stdout") == 0 && (flag & O_ACCMODE) == O_WRONLY)
1558 openfd = fileno(stdout);
1559 else if (strcmp(cp, "stderr") == 0 && (flag & O_ACCMODE) == O_WRONLY)
1560 openfd = fileno(stderr);
1561 else if (strncmp(cp, "fd/", 3) == 0) {
1565 openfd = (int) strtoul(cp, & ptr, 10);
1566 if (openfd <= INVALID_HANDLE || ptr == cp
1567 || fstat(openfd, & sbuf) < 0)
1568 openfd = INVALID_HANDLE;
1570 /* do not set close-on-exec for inherited fd's */
1571 if (openfd != INVALID_HANDLE)
1573 } else if (inetfile(name, & len, & family)) {
1575 /* /inet/protocol/localport/hostname/remoteport */
1578 char *hostnameslastcharp;
1580 char *localpnamelastcharp;
1582 cp = (char *) name + len;
1583 /* which protocol? */
1584 if (strncmp(cp, "tcp/", 4) == 0)
1585 protocol = SOCK_STREAM;
1586 else if (strncmp(cp, "udp/", 4) == 0)
1587 protocol = SOCK_DGRAM;
1589 protocol = SOCK_STREAM; /* shut up the compiler */
1590 fatal(_("no (known) protocol supplied in special filename `%s'"),
1595 /* which localport? */
1597 while (*cp != '/' && *cp != '\0')
1600 * Require a port, let them explicitly put 0 if
1603 if (*cp != '/' || cp == localpname)
1604 fatal(_("special file name `%s' is incomplete"), name);
1607 * We change the special file name temporarily because we
1608 * need a 0-terminated string here for conversion with atoi().
1609 * By using atoi() the use of decimal numbers is enforced.
1612 localpnamelastcharp = cp;
1614 /* which hostname? */
1617 while (*cp != '/' && *cp != '\0')
1619 if (*cp != '/' || cp == hostname) {
1620 *localpnamelastcharp = '/';
1621 fatal(_("must supply a remote hostname to `/inet'"));
1624 hostnameslastcharp = cp;
1626 /* which remoteport? */
1629 * The remote port ends the special file name.
1630 * This means there already is a '\0' at the end of the string.
1631 * Therefore no need to patch any string ending.
1633 * Here too, require a port, let them explicitly put 0 if
1637 *localpnamelastcharp = '/';
1638 *hostnameslastcharp = '/';
1639 fatal(_("must supply a remote port to `/inet'"));
1643 #define DEFAULT_RETRIES 20
1644 static unsigned long def_retries = DEFAULT_RETRIES;
1645 static bool first_time = true;
1646 unsigned long retries = 0;
1647 static long msleep = 1000;
1651 unsigned long count = 0;
1655 if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) {
1656 count = strtoul(cp, & end, 10);
1657 if (end != cp && count > 0)
1658 def_retries = count;
1662 * Env var is in milliseconds, paramter to usleep()
1663 * is microseconds, make the conversion. Default is
1666 if ((ms2 = getenv("GAWK_MSEC_SLEEP")) != NULL) {
1667 msleep = strtol(ms2, & end, 10);
1668 if (end == ms2 || msleep < 0)
1674 retries = def_retries;
1677 openfd = socketopen(family, protocol, localpname, cp, hostname);
1679 } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0);
1682 *localpnamelastcharp = '/';
1683 *hostnameslastcharp = '/';
1684 #else /* ! HAVE_SOCKETS */
1685 fatal(_("TCP/IP communications are not supported"));
1686 #endif /* HAVE_SOCKETS */
1690 if (openfd == INVALID_HANDLE)
1691 openfd = open(name, flag, 0666);
1692 #if defined(__EMX__) || defined(__MINGW32__)
1693 if (openfd == INVALID_HANDLE && errno == EACCES) {
1694 /* On OS/2 and Windows directory access via open() is
1699 if (!inetfile(name, &l, &f)
1700 && stat(name, & buf) == 0 && S_ISDIR(buf.st_mode))
1704 if (openfd != INVALID_HANDLE) {
1705 if (openfd > fileno(stderr))
1706 os_close_on_exec(openfd, name, "file", "");
1712 /* two_way_open --- open a two way communications channel */
1715 two_way_open(const char *str, struct redirect *rp)
1717 static bool no_ptys = false;
1720 /* case 1: socket */
1721 if (inetfile(str, NULL, NULL)) {
1724 fd = devopen(str, "rw");
1725 if (fd == INVALID_HANDLE)
1727 if ((BINMODE & BINMODE_OUTPUT) != 0)
1728 os_setbinmode(fd, O_BINARY);
1729 rp->output.fp = fdopen(fd, binmode("wb"));
1730 if (rp->output.fp == NULL) {
1736 rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1739 if ((BINMODE & BINMODE_INPUT) != 0)
1740 os_setbinmode(newfd, O_BINARY);
1741 os_close_on_exec(fd, str, "socket", "to/from");
1742 os_close_on_exec(newfd, str, "socket", "to/from");
1743 rp->iop = iop_alloc(newfd, str, 0);
1744 rp->output.name = str;
1745 find_input_parser(rp->iop);
1746 iop_finish(rp->iop);
1747 if (! rp->iop->valid) {
1748 if (! do_traditional && rp->iop->errcode != 0)
1749 update_ERRNO_int(rp->iop->errcode);
1752 rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1755 rp->flag |= RED_SOCKET;
1758 #endif /* HAVE_SOCKETS */
1760 /* case 2: see if an extension wants it */
1761 if (find_two_way_processor(str, rp))
1764 #if defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS)
1765 /* case 3: use ptys for two-way communications to child */
1766 if (! no_ptys && pty_vs_pipe(str)) {
1767 static bool initialized = false;
1768 static char first_pty_letter;
1769 #if defined(HAVE_GRANTPT) && ! defined(HAVE_POSIX_OPENPT)
1770 static int have_dev_ptmx;
1774 int master, dup_master;
1780 /* Use array of chars to avoid ASCII / EBCDIC issues */
1781 static char pty_chars[] = "pqrstuvwxyzabcdefghijklmno";
1784 if (! initialized) {
1786 #if defined(HAVE_GRANTPT) && ! defined(HAVE_POSIX_OPENPT)
1787 have_dev_ptmx = (stat("/dev/ptmx", & statb) >= 0);
1792 sprintf(slavenam, "/dev/pty%c0", c);
1793 if (stat(slavenam, & statb) >= 0) {
1794 first_pty_letter = c;
1797 } while (pty_chars[i] != '\0');
1801 #ifdef HAVE_POSIX_OPENPT
1803 master = posix_openpt(O_RDWR|O_NOCTTY);
1805 if (have_dev_ptmx) {
1806 master = open("/dev/ptmx", O_RDWR);
1813 tem = ptsname(master);
1815 strcpy(slavenam, tem);
1818 (void) close(master);
1823 if (first_pty_letter) {
1825 * Assume /dev/ptyXNN and /dev/ttyXN naming system.
1826 * The FIRST_PTY_LETTER gives the first X to try.
1827 * We try in the sequence FIRST_PTY_LETTER, ..,
1828 * 'z', 'a', .., FIRST_PTY_LETTER.
1829 * Is this worthwhile, or just over-zealous?
1831 c = first_pty_letter;
1836 for (i = 0; i < 16; i++) {
1837 sprintf(slavenam, "/dev/pty%c%x", c, i);
1838 if (stat(slavenam, & statb) < 0) {
1839 no_ptys = true; /* bypass all this next time */
1843 if ((master = open(slavenam, O_RDWR)) >= 0) {
1844 slavenam[sizeof("/dev/") - 1] = 't';
1845 if (access(slavenam, R_OK | W_OK) == 0)
1850 /* move to next character */
1851 cp = strchr(pty_chars, c);
1857 } while (c != first_pty_letter);
1861 /* Couldn't find a pty. Fall back to using pipes. */
1865 if ((slave = open(slavenam, O_RDWR)) < 0) {
1867 fatal(_("could not open `%s', mode `%s'"),
1873 * Push the necessary modules onto the slave to
1874 * get terminal semantics.
1876 ioctl(slave, I_PUSH, "ptem");
1877 ioctl(slave, I_PUSH, "ldterm");
1880 tcgetattr(slave, & st);
1881 st.c_iflag &= ~(ISTRIP | IGNCR | INLCR | IXOFF);
1882 st.c_iflag |= (ICRNL | IGNPAR | BRKINT | IXON);
1883 st.c_oflag &= ~OPOST;
1884 st.c_cflag &= ~CSIZE;
1885 st.c_cflag |= CREAD | CS8 | CLOCAL;
1886 st.c_lflag &= ~(ECHO | ECHOE | ECHOK | NOFLSH | TOSTOP);
1889 /* Set some control codes to default values */
1891 st.c_cc[VINTR] = '\003'; /* ^c */
1894 st.c_cc[VQUIT] = '\034'; /* ^| */
1897 st.c_cc[VERASE] = '\177'; /* ^? */
1900 st.c_cc[VKILL] = '\025'; /* ^u */
1903 st.c_cc[VEOF] = '\004'; /* ^d */
1905 tcsetattr(slave, TCSANOW, & st);
1907 switch (pid = fork()) {
1913 ioctl(slave, TIOCSCTTY, 0);
1916 if (close(master) == -1)
1917 fatal(_("close of master pty failed (%s)"), strerror(errno));
1919 fatal(_("close of stdout in child failed (%s)"),
1921 if (dup(slave) != 1)
1922 fatal(_("moving slave pty to stdout in child failed (dup: %s)"), strerror(errno));
1924 fatal(_("close of stdin in child failed (%s)"),
1926 if (dup(slave) != 0)
1927 fatal(_("moving slave pty to stdin in child failed (dup: %s)"), strerror(errno));
1929 fatal(_("close of slave pty failed (%s)"), strerror(errno));
1931 /* stderr does NOT get dup'ed onto child's stdout */
1933 signal(SIGPIPE, SIG_DFL);
1935 execl("/bin/sh", "sh", "-c", str, NULL);
1936 _exit(errno == ENOENT ? 127 : 126);
1948 if (close(slave) != 0) {
1950 (void) kill(pid, SIGKILL);
1951 fatal(_("close of slave pty failed (%s)"), strerror(errno));
1955 rp->iop = iop_alloc(master, str, 0);
1956 find_input_parser(rp->iop);
1957 iop_finish(rp->iop);
1958 if (! rp->iop->valid) {
1959 if (! do_traditional && rp->iop->errcode != 0)
1960 update_ERRNO_int(rp->iop->errcode);
1963 (void) kill(pid, SIGKILL);
1967 rp->output.name = str;
1969 * Force read and write ends of two-way connection to
1970 * be different fd's so they can be closed independently.
1972 rp->output.mode = "w";
1973 if ((dup_master = dup(master)) < 0
1974 || (rp->output.fp = fdopen(dup_master, "w")) == NULL) {
1977 (void) close(master);
1978 (void) kill(pid, SIGKILL);
1980 (void) close(dup_master);
1983 find_output_wrapper(& rp->output);
1984 rp->flag |= RED_PTY;
1985 os_close_on_exec(master, str, "pipe", "from");
1986 os_close_on_exec(dup_master, str, "pipe", "to");
1987 first_pty_letter = '\0'; /* reset for next command */
1990 #endif /* defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS) */
1993 #ifndef PIPES_SIMULATED /* real pipes */
1994 /* case 4: two way pipe to a child process */
1996 int ptoc[2], ctop[2];
1999 #if defined(__EMX__) || defined(__MINGW32__)
2000 int save_stdout, save_stdin;
2007 return false; /* errno set, diagnostic from caller */
2009 if (pipe(ctop) < 0) {
2017 #if defined(__EMX__) || defined(__MINGW32__)
2018 save_stdin = dup(0); /* duplicate stdin */
2019 save_stdout = dup(1); /* duplicate stdout */
2021 if (save_stdout == -1 || save_stdin == -1) {
2022 /* if an error occurs close all open file handles */
2024 if (save_stdin != -1)
2026 if (save_stdout != -1)
2028 close(ptoc[0]); close(ptoc[1]);
2029 close(ctop[0]); close(ctop[1]);
2034 /* connect pipes to stdin and stdout */
2035 close(1); /* close stdout */
2036 if (dup(ctop[1]) != 1) { /* connect pipe input to stdout */
2037 close(save_stdin); close(save_stdout);
2038 close(ptoc[0]); close(ptoc[1]);
2039 close(ctop[0]); close(ctop[1]);
2040 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
2042 close(0); /* close stdin */
2043 if (dup(ptoc[0]) != 0) { /* connect pipe output to stdin */
2044 close(save_stdin); close(save_stdout);
2045 close(ptoc[0]); close(ptoc[1]);
2046 close(ctop[0]); close(ctop[1]);
2047 fatal(_("moving pipe to stdin in child failed (dup: %s)"), strerror(errno));
2050 /* none of these handles must be inherited by the child process */
2051 (void) close(ptoc[0]); /* close pipe output, child will use stdin instead */
2052 (void) close(ctop[1]); /* close pipe input, child will use stdout instead */
2054 os_close_on_exec(ptoc[1], str, "pipe", "from"); /* pipe input: output of the parent process */
2055 os_close_on_exec(ctop[0], str, "pipe", "from"); /* pipe output: input of the parent process */
2056 os_close_on_exec(save_stdin, str, "pipe", "from"); /* saved stdin of the parent process */
2057 os_close_on_exec(save_stdout, str, "pipe", "from"); /* saved stdout of the parent process */
2059 /* stderr does NOT get dup'ed onto child's stdout */
2061 pid = spawnl(P_NOWAIT, "/bin/sh", "sh", "-c", str, NULL);
2062 #else /* __MINGW32__ */
2063 pid = spawnl(P_NOWAIT, getenv("ComSpec"), "cmd.exe", "/c",
2064 qcmd = quote_cmd(str), NULL);
2068 /* restore stdin and stdout */
2070 if (dup(save_stdout) != 1) {
2071 close(save_stdin); close(save_stdout);
2072 close(ptoc[1]); close(ctop[0]);
2073 fatal(_("restoring stdout in parent process failed\n"));
2078 if (dup(save_stdin) != 0) {
2080 close(ptoc[1]); close(ctop[0]);
2081 fatal(_("restoring stdin in parent process failed\n"));
2085 if (pid < 0) { /* spawnl() failed */
2094 #else /* NOT __EMX__, NOT __MINGW32__ */
2095 if ((pid = fork()) < 0) {
2097 close(ptoc[0]); close(ptoc[1]);
2098 close(ctop[0]); close(ctop[1]);
2103 if (pid == 0) { /* child */
2105 fatal(_("close of stdout in child failed (%s)"),
2107 if (dup(ctop[1]) != 1)
2108 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
2110 fatal(_("close of stdin in child failed (%s)"),
2112 if (dup(ptoc[0]) != 0)
2113 fatal(_("moving pipe to stdin in child failed (dup: %s)"), strerror(errno));
2114 if ( close(ptoc[0]) == -1 || close(ptoc[1]) == -1
2115 || close(ctop[0]) == -1 || close(ctop[1]) == -1)
2116 fatal(_("close of pipe failed (%s)"), strerror(errno));
2117 /* stderr does NOT get dup'ed onto child's stdout */
2118 execl("/bin/sh", "sh", "-c", str, NULL);
2119 _exit(errno == ENOENT ? 127 : 126);
2121 #endif /* NOT __EMX__, NOT __MINGW32__ */
2124 if ((BINMODE & BINMODE_INPUT) != 0)
2125 os_setbinmode(ctop[0], O_BINARY);
2126 if ((BINMODE & BINMODE_OUTPUT) != 0)
2127 os_setbinmode(ptoc[1], O_BINARY);
2129 rp->iop = iop_alloc(ctop[0], str, 0);
2130 find_input_parser(rp->iop);
2131 iop_finish(rp->iop);
2132 if (! rp->iop->valid) {
2133 if (! do_traditional && rp->iop->errcode != 0)
2134 update_ERRNO_int(rp->iop->errcode);
2137 (void) close(ctop[1]);
2138 (void) close(ptoc[0]);
2139 (void) close(ptoc[1]);
2140 (void) kill(pid, SIGKILL);
2144 rp->output.fp = fdopen(ptoc[1], binmode("w"));
2145 rp->output.mode = "w";
2146 rp->output.name = str;
2147 if (rp->output.fp == NULL) {
2150 (void) close(ctop[0]);
2151 (void) close(ctop[1]);
2152 (void) close(ptoc[0]);
2153 (void) close(ptoc[1]);
2154 (void) kill(pid, SIGKILL);
2159 find_output_wrapper(& rp->output);
2161 #if !defined(__EMX__) && !defined(__MINGW32__)
2162 os_close_on_exec(ctop[0], str, "pipe", "from");
2163 os_close_on_exec(ptoc[1], str, "pipe", "from");
2165 (void) close(ptoc[0]);
2166 (void) close(ctop[1]);
2172 #else /*PIPES_SIMULATED*/
2174 fatal(_("`|&' not supported"));
2181 #ifndef PIPES_SIMULATED /* real pipes */
2183 /* wait_any --- wait for a child process, close associated pipe */
2186 wait_any(int interesting) /* pid of interest, if any */
2188 RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int);
2191 struct redirect *redp;
2193 istat = signal(SIGINT, SIG_IGN);
2195 if (interesting < 0) {
2200 pid = _cwait(& status, interesting, 0);
2201 if (pid == interesting && pid > 0) {
2202 for (redp = red_head; redp != NULL; redp = redp->next)
2203 if (interesting == redp->pid) {
2205 redp->status = status;
2210 hstat = signal(SIGHUP, SIG_IGN);
2211 qstat = signal(SIGQUIT, SIG_IGN);
2213 # ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */
2214 pid = wait(& status);
2216 pid = wait((union wait *) & status);
2218 if (interesting && pid == interesting) {
2220 } else if (pid != -1) {
2221 for (redp = red_head; redp != NULL; redp = redp->next)
2222 if (pid == redp->pid) {
2224 redp->status = status;
2228 if (pid == -1 && errno == ECHILD)
2231 signal(SIGHUP, hstat);
2232 signal(SIGQUIT, qstat);
2234 signal(SIGINT, istat);
2238 /* gawk_popen --- open an IOBUF on a child process */
2241 gawk_popen(const char *cmd, struct redirect *rp)
2245 #if defined(__EMX__) || defined(__MINGW32__)
2253 * We used to wait for any children to synchronize input and output,
2254 * but this could cause gawk to hang when it is started in a pipeline
2255 * and thus has a child process feeding it input (shell dependent).
2257 * (void) wait_any(0); // wait for outstanding processes
2261 fatal(_("cannot open pipe `%s' (%s)"), cmd, strerror(errno));
2263 #if defined(__EMX__) || defined(__MINGW32__)
2265 save_stdout = dup(1); /* save stdout */
2266 if (save_stdout == -1) {
2269 return NULL; /* failed */
2272 close(1); /* close stdout */
2273 if (dup(p[1]) != 1) {
2276 fatal(_("moving pipe to stdout in child failed (dup: %s)"),
2280 /* none of these handles must be inherited by the child process */
2281 close(p[1]); /* close pipe input */
2283 os_close_on_exec(p[0], cmd, "pipe", "from"); /* pipe output: input of the parent process */
2284 os_close_on_exec(save_stdout, cmd, "pipe", "from"); /* saved stdout of the parent process */
2287 pid = spawnl(P_NOWAIT, "/bin/sh", "sh", "-c", cmd, NULL);
2288 #else /* __MINGW32__ */
2289 pid = spawnl(P_NOWAIT, getenv("ComSpec"), "cmd.exe", "/c",
2290 qcmd = quote_cmd(cmd), NULL);
2294 /* restore stdout */
2296 if (dup(save_stdout) != 1) {
2298 fatal(_("restoring stdout in parent process failed\n"));
2302 #else /* NOT __EMX__, NOT __MINGW32__ */
2303 if ((pid = fork()) == 0) {
2305 fatal(_("close of stdout in child failed (%s)"),
2308 fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
2309 if (close(p[0]) == -1 || close(p[1]) == -1)
2310 fatal(_("close of pipe failed (%s)"), strerror(errno));
2311 execl("/bin/sh", "sh", "-c", cmd, NULL);
2312 _exit(errno == ENOENT ? 127 : 126);
2314 #endif /* NOT __EMX__, NOT __MINGW32__ */
2317 close(p[0]); close(p[1]);
2318 fatal(_("cannot create child process for `%s' (fork: %s)"), cmd, strerror(errno));
2321 #if !defined(__EMX__) && !defined(__MINGW32__)
2322 if (close(p[1]) == -1) {
2324 fatal(_("close of pipe failed (%s)"), strerror(errno));
2327 os_close_on_exec(p[0], cmd, "pipe", "from");
2328 if ((BINMODE & BINMODE_INPUT) != 0)
2329 os_setbinmode(p[0], O_BINARY);
2330 rp->iop = iop_alloc(p[0], cmd, 0);
2331 find_input_parser(rp->iop);
2332 iop_finish(rp->iop);
2333 if (! rp->iop->valid) {
2334 if (! do_traditional && rp->iop->errcode != 0)
2335 update_ERRNO_int(rp->iop->errcode);
2343 /* gawk_pclose --- close an open child pipe */
2346 gawk_pclose(struct redirect *rp)
2348 if (rp->iop != NULL)
2349 (void) iop_close(rp->iop);
2352 /* process previously found, return stored status */
2355 rp->status = wait_any(rp->pid);
2360 #else /* PIPES_SIMULATED */
2363 * use temporary file rather than pipe
2364 * except if popen() provides real pipes too
2367 /* gawk_popen --- open an IOBUF on a child process */
2370 gawk_popen(const char *cmd, struct redirect *rp)
2374 os_restore_mode(fileno(stdin));
2375 current = popen(cmd, binmode("r"));
2376 if ((BINMODE & BINMODE_INPUT) != 0)
2377 os_setbinmode(fileno(stdin), O_BINARY);
2378 if (current == NULL)
2380 os_close_on_exec(fileno(current), cmd, "pipe", "from");
2381 rp->iop = iop_alloc(fileno(current), cmd, 0);
2382 find_input_parser(rp->iop);
2383 iop_finish(rp->iop);
2384 if (! rp->iop->valid) {
2385 if (! do_traditional && rp->iop->errcode != 0)
2386 update_ERRNO_int(rp->iop->errcode);
2387 (void) pclose(current);
2388 rp->iop->public.fd = INVALID_HANDLE;
2397 /* gawk_pclose --- close an open child pipe */
2400 gawk_pclose(struct redirect *rp)
2402 int rval, aval, fd = rp->iop->public.fd;
2404 if (rp->iop != NULL) {
2405 rp->iop->public.fd = dup(fd); /* kludge to allow close() + pclose() */
2406 rval = iop_close(rp->iop);
2409 aval = pclose(rp->ifp);
2411 return (rval < 0 ? rval : aval);
2414 #endif /* PIPES_SIMULATED */
2416 /* do_getline_redir --- read in a line, into var and with redirection */
2419 do_getline_redir(int into_variable, enum redirval redirtype)
2421 struct redirect *rp = NULL;
2426 NODE *redir_exp = NULL;
2428 int redir_error = 0;
2431 lhs = POP_ADDRESS();
2433 assert(redirtype != redirect_none);
2435 rp = redirect(redir_exp, redirtype, & redir_error);
2439 if (redir_error) { /* failed redirect */
2440 if (! do_traditional)
2441 update_ERRNO_int(redir_error);
2443 return make_number((AWKNUM) -1.0);
2446 if (iop == NULL) /* end of input */
2447 return make_number((AWKNUM) 0.0);
2450 cnt = get_a_record(& s, iop, & errcode);
2452 if (! do_traditional && (errcode != -1))
2453 update_ERRNO_int(errcode);
2454 return make_number((AWKNUM) -1.0);
2459 * Don't do iop_close() here if we are
2460 * reading from a pipe; otherwise
2461 * gawk_pclose will not be called.
2463 if ((rp->flag & (RED_PIPE|RED_TWOWAY)) == 0) {
2464 (void) iop_close(iop);
2467 rp->flag |= RED_EOF; /* sticky EOF */
2468 return make_number((AWKNUM) 0.0);
2471 if (lhs == NULL) /* no optional var. */
2473 else { /* assignment to variable */
2475 *lhs = make_string(s, cnt);
2476 (*lhs)->flags |= MAYBE_NUM;
2479 return make_number((AWKNUM) 1.0);
2482 /* do_getline --- read in a line, into var and without redirection */
2485 do_getline(int into_variable, IOBUF *iop)
2491 if (iop == NULL) { /* end of input */
2493 (void) POP_ADDRESS();
2494 return make_number((AWKNUM) 0.0);
2498 cnt = get_a_record(& s, iop, & errcode);
2500 if (! do_traditional && (errcode != -1))
2501 update_ERRNO_int(errcode);
2503 (void) POP_ADDRESS();
2504 return make_number((AWKNUM) -1.0);
2508 return NULL; /* try next file */
2512 if (! into_variable) /* no optional var. */
2514 else { /* assignment to variable */
2516 lhs = POP_ADDRESS();
2518 *lhs = make_string(s, cnt);
2519 (*lhs)->flags |= MAYBE_NUM;
2521 return make_number((AWKNUM) 1.0);
2525 const char *envname;
2526 char **dfltp; /* pointer to address of default path */
2527 char try_cwd; /* always search current directory? */
2528 char **awkpath; /* array containing library search paths */
2529 int max_pathlen; /* length of the longest item in awkpath */
2532 static path_info pi_awkpath = {
2533 /* envname */ "AWKPATH",
2534 /* dfltp */ & defpath,
2538 static path_info pi_awklibpath = {
2539 /* envname */ "AWKLIBPATH",
2540 /* dfltp */ & deflibpath,
2541 /* try_cwd */ false,
2544 /* init_awkpath --- split path(=$AWKPATH) into components */
2547 init_awkpath(path_info *pi)
2550 char *start, *end, *p;
2552 int max_path; /* (# of allocated paths)-1 */
2556 pi->max_pathlen = 0;
2557 if ((path = getenv(pi->envname)) == NULL || *path == '\0')
2558 path = pi->dfltp[0];
2560 max_path = INC_PATH;
2561 emalloc(pi->awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath");
2562 memset(pi->awkpath, 0, (max_path + 1) * sizeof(char *));
2567 while (*end && *end != envsep)
2571 emalloc(p, char *, len + 2, "init_awkpath");
2572 memcpy(p, start, len);
2574 /* add directory punctuation if necessary */
2575 if (! isdirpunct(end[-1]))
2579 if (i == max_path) {
2580 max_path += INC_PATH;
2581 erealloc(pi->awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath");
2582 memset(pi->awkpath + i, 0, (INC_PATH + 1) * sizeof(char *));
2584 pi->awkpath[i++] = p;
2585 if (len > pi->max_pathlen)
2586 pi->max_pathlen = len;
2589 /* skip one or more envsep char */
2590 while (*end && *end == envsep)
2594 pi->awkpath[i] = NULL;
2599 /* get_cwd -- get current working directory */
2606 size_t bsize = BSIZE;
2608 emalloc(buf, char *, bsize * sizeof(char), "get_cwd");
2610 if (getcwd(buf, bsize) == buf)
2612 if (errno != ERANGE) {
2617 erealloc(buf, char *, bsize * sizeof(char), "get_cwd");
2623 /* do_find_source --- search $AWKPATH for file, return NULL if not found */
2626 do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi)
2631 assert(errcode != NULL);
2633 /* some kind of path name, no search */
2635 emalloc(path, char *, strlen(src) + 1, "do_find_source");
2637 if (stat(path, stb) == 0)
2644 /* try current directory before $AWKPATH search */
2645 if (pi->try_cwd && stat(src, stb) == 0) {
2651 erealloc(path, char *, strlen(path) + strlen(src) + 2, "do_find_source");
2653 if (strcspn(path,">]:") == strlen(path))
2662 if (pi->awkpath == NULL)
2665 emalloc(path, char *, pi->max_pathlen + strlen(src) + 1, "do_find_source");
2666 for (i = 0; pi->awkpath[i] != NULL; i++) {
2667 if (strcmp(pi->awkpath[i], "./") == 0 || strcmp(pi->awkpath[i], ".") == 0)
2670 strcpy(path, pi->awkpath[i]);
2672 if (stat(path, stb) == 0)
2676 /* not found, give up */
2682 /* find_source --- find source file with default file extension handling */
2685 find_source(const char *src, struct stat *stb, int *errcode, int is_extlib)
2688 path_info *pi = (is_extlib ? & pi_awklibpath : & pi_awkpath);
2691 if (src == NULL || *src == '\0')
2693 path = do_find_source(src, stb, errcode, pi);
2695 if (path == NULL && is_extlib) {
2701 #define EXTLIB_SUFFIX "." SHLIBEXT
2702 src_len = strlen(src);
2703 suffix_len = strlen(EXTLIB_SUFFIX);
2705 /* check if already has the SUFFIX */
2706 if (src_len >= suffix_len && strcmp(& src[src_len - suffix_len], EXTLIB_SUFFIX) == 0)
2709 /* append EXTLIB_SUFFIX and try again */
2711 emalloc(file_ext, char *, src_len + suffix_len + 1, "find_source");
2712 sprintf(file_ext, "%s%s", src, EXTLIB_SUFFIX);
2713 path = do_find_source(file_ext, stb, errcode, pi);
2718 #undef EXTLIB_SUFFIX
2722 * Try searching with .awk appended if the platform headers have not specified
2725 #ifndef DEFAULT_FILETYPE
2726 #define DEFAULT_FILETYPE ".awk"
2729 #ifdef DEFAULT_FILETYPE
2730 if (! do_traditional && path == NULL) {
2732 int save_errno = errno;
2734 int vms_save = vaxc$errno;
2737 /* append ".awk" and try again */
2738 emalloc(file_awk, char *, strlen(src) +
2739 sizeof(DEFAULT_FILETYPE) + 1, "find_source");
2740 sprintf(file_awk, "%s%s", src, DEFAULT_FILETYPE);
2741 path = do_find_source(file_awk, stb, errcode, pi);
2746 vaxc$errno = vms_save;
2750 #endif /*DEFAULT_FILETYPE*/
2756 /* srcopen --- open source file */
2761 int fd = INVALID_HANDLE;
2763 if (s->stype == SRC_STDIN)
2765 else if (s->stype == SRC_FILE || s->stype == SRC_INC)
2766 fd = devopen(s->fullpath, "r");
2768 /* set binary mode so that debugger byte offset calculations will be right */
2769 if (fd != INVALID_HANDLE)
2770 os_setbinmode(fd, O_BINARY);
2775 /* input parsers, mainly for use by extension functions */
2777 static awk_input_parser_t *ip_head, *ip_tail;
2780 * register_input_parser --- add an input parser to the list, FIFO.
2781 * The main reason to use FIFO is to provide the diagnostic
2782 * with the correct information: input parser 2 conflicts
2783 * with input parser 1. Otherwise LIFO would have been easier.
2787 register_input_parser(awk_input_parser_t *input_parser)
2789 if (input_parser == NULL)
2790 fatal(_("register_input_parser: received NULL pointer"));
2792 input_parser->next = NULL; /* force it */
2793 if (ip_head == NULL) {
2794 ip_head = ip_tail = input_parser;
2796 ip_tail->next = input_parser;
2797 ip_tail = ip_tail->next;
2801 /* find_input_parser --- search the list of input parsers */
2804 find_input_parser(IOBUF *iop)
2806 awk_input_parser_t *ip, *ip2;
2808 /* if already associated with an input parser, bail out early */
2809 if (iop->public.get_record != NULL)
2813 for (ip2 = ip_head; ip2 != NULL; ip2 = ip2->next) {
2814 if (ip2->can_take_file(& iop->public)) {
2816 ip = ip2; /* found first one */
2818 fatal(_("input parser `%s' conflicts with previously installed input parser `%s'"),
2819 ip2->name, ip->name);
2824 if (! ip->take_control_of(& iop->public))
2825 warning(_("input parser `%s' failed to open `%s'"),
2826 ip->name, iop->public.name);
2832 /* output wrappers --- for use by extensions */
2834 static awk_output_wrapper_t *op_head, *op_tail;
2837 * register_output_wrapper --- add an output wrapper to the list.
2838 * Same stuff here as for input parsers.
2842 register_output_wrapper(awk_output_wrapper_t *wrapper)
2844 if (wrapper == NULL)
2845 fatal(_("register_output_wrapper: received NULL pointer"));
2847 wrapper->next = NULL; /* force it */
2848 if (op_head == NULL) {
2849 op_head = op_tail = wrapper;
2851 op_tail->next = wrapper;
2852 op_tail = op_tail->next;
2856 /* find_output_wrapper --- search the list of output wrappers */
2859 find_output_wrapper(awk_output_buf_t *outbuf)
2861 awk_output_wrapper_t *op, *op2;
2863 /* if already associated with an output wrapper, bail out early */
2864 if (outbuf->redirected)
2868 for (op2 = op_head; op2 != NULL; op2 = op2->next) {
2869 if (op2->can_take_file(outbuf)) {
2871 op = op2; /* found first one */
2873 fatal(_("output wrapper `%s' conflicts with previously installed output wrapper `%s'"),
2874 op2->name, op->name);
2879 if (! op->take_control_of(outbuf)) {
2880 warning(_("output wrapper `%s' failed to open `%s'"),
2881 op->name, outbuf->name);
2891 /* two way processors --- for use by extensions */
2893 static awk_two_way_processor_t *tw_head, *tw_tail;
2895 /* register_two_way_processor --- register a two-way I/O processor, for extensions */
2898 register_two_way_processor(awk_two_way_processor_t *processor)
2900 if (processor == NULL)
2901 fatal(_("register_output_processor: received NULL pointer"));
2903 processor->next = NULL; /* force it */
2904 if (tw_head == NULL) {
2905 tw_head = tw_tail = processor;
2907 tw_tail->next = processor;
2908 tw_tail = tw_tail->next;
2912 /* find_two_way_processor --- search the list of two way processors */
2915 find_two_way_processor(const char *name, struct redirect *rp)
2917 awk_two_way_processor_t *tw, *tw2;
2919 /* if already associated with i/o, bail out early */
2920 if ( (rp->iop != NULL && rp->iop->public.fd != INVALID_HANDLE)
2921 || rp->output.fp != NULL)
2925 for (tw2 = tw_head; tw2 != NULL; tw2 = tw2->next) {
2926 if (tw2->can_take_two_way(name)) {
2928 tw = tw2; /* found first one */
2930 fatal(_("two-way processor `%s' conflicts with previously installed two-way processor `%s'"),
2931 tw2->name, tw->name);
2936 if (rp->iop == NULL)
2937 rp->iop = iop_alloc(INVALID_HANDLE, name, 0);
2938 if (! tw->take_control_of(name, & rp->iop->public, & rp->output)) {
2939 warning(_("two way processor `%s' failed to open `%s'"),
2943 iop_finish(rp->iop);
2951 * IOBUF management is somewhat complicated. In particular,
2952 * it is possible and OK for an IOBUF to be allocated with
2953 * a file descriptor that is either valid or not usable with
2954 * read(2), in case an input parser will come along later and
2955 * make it readable. Alternatively, an input parser can simply
2956 * come along and take over reading on a valid readable descriptor.
2958 * The first stage is simply to allocate the IOBUF. This is done
2959 * during nextfile() for command line files and by redirect()
2960 * and other routines for getline, input pipes, and the input
2961 * side of a two-way pipe.
2963 * The second stage is to check for input parsers. This is done
2964 * for command line files in after_beginfile() and for the others
2965 * as part of the full flow. At this point, either:
2966 * - The fd is valid on a readable file
2967 * - The input parser has taken over a valid fd and made
2968 * it usable (e.g., directories)
2969 * - Or the input parser has simply hijacked the reading
2970 * (such as the gawkextlib XML extension)
2971 * If none of those are true, the fd should be closed, reset
2972 * to INVALID_HANDLE, and iop->errcode set to indicate the error
2973 * (EISDIR for directories, EIO for anything else).
2974 * iop->valid should be set to false in this case.
2976 * Otherwise, after the second stage, iop->errcode should be
2977 * zero, iop->valid should be true, and iop->public.fd should
2978 * not be INVALID_HANDLE.
2980 * The third stage is to set up the rest of the IOBUF for
2981 * use by get_a_record(). In this case, iop->valid must
2982 * be true already, and iop->public.fd cannot be INVALID_HANDLE.
2984 * Checking for input parsers for command line files is delayed
2985 * to after_beginfile() so that the BEGINFILE rule has an
2986 * opportunity to look at FILENAME and ERRNO and attempt to
2987 * recover with a custom input parser. The XML extension, in
2988 * particular, relies strongly upon this ability.
2991 /* iop_alloc --- allocate an IOBUF structure for an open fd */
2994 iop_alloc(int fd, const char *name, int errno_val)
2998 emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
3000 memset(iop, '\0', sizeof(IOBUF));
3001 iop->public.fd = fd;
3002 iop->public.name = name;
3003 iop->public.read_func = ( ssize_t(*)() ) read;
3005 iop->errcode = errno_val;
3007 if (fd != INVALID_HANDLE)
3008 fstat(fd, & iop->public.sbuf);
3009 #if defined(__EMX__) || defined(__MINGW32__)
3010 else if (errno_val == EISDIR) {
3011 iop->public.sbuf.st_mode = (_S_IFDIR | _S_IRWXU);
3012 iop->public.fd = FAKE_FD_VALUE;
3019 /* iop_finish --- finish setting up an IOBUF */
3022 iop_finish(IOBUF *iop)
3026 if (iop->public.fd != INVALID_HANDLE) {
3027 if (os_isreadable(& iop->public, & isdir))
3031 iop->errcode = EISDIR;
3035 * Extensions can supply values that are not
3036 * INVALID_HANDLE but that are also not real
3037 * file descriptors. So check the fd before
3038 * trying to close it, which avoids errors
3039 * on some operating systems.
3041 * The fcntl call works for Windows, too.
3043 #if defined(F_GETFL)
3044 if (fcntl(iop->public.fd, F_GETFL) >= 0)
3046 (void) close(iop->public.fd);
3047 iop->public.fd = INVALID_HANDLE;
3050 * Don't close directories: after_beginfile(),
3051 * special cases them.
3056 if (! iop->valid || iop->public.fd == INVALID_HANDLE)
3059 if (os_isatty(iop->public.fd))
3060 iop->flag |= IOP_IS_TTY;
3062 iop->readsize = iop->size = optimal_bufsize(iop->public.fd, & iop->public.sbuf);
3063 if (do_lint && S_ISREG(iop->public.sbuf.st_mode) && iop->public.sbuf.st_size == 0)
3064 lintwarn(_("data file `%s' is empty"), iop->public.name);
3065 iop->errcode = errno = 0;
3066 iop->count = iop->scanoff = 0;
3067 emalloc(iop->buf, char *, iop->size += 2, "iop_finish");
3068 iop->off = iop->buf;
3069 iop->dataend = NULL;
3070 iop->end = iop->buf + iop->size;
3071 iop->flag |= IOP_AT_START;
3076 #define set_RT_to_null() \
3077 (void)(! do_traditional && (unref(RT_node->var_value), \
3078 RT_node->var_value = dupnode(Nnull_string)))
3080 #define set_RT(str, len) \
3081 (void)(! do_traditional && (unref(RT_node->var_value), \
3082 RT_node->var_value = make_string(str, len)))
3087 * grow must increase size of buffer, set end, make sure off and dataend
3088 * point at the right spot.
3092 grow_iop_buffer(IOBUF *iop)
3094 size_t valid = iop->dataend - iop->off;
3095 size_t off = iop->off - iop->buf;
3099 * Lop off original extra two bytes, double the size,
3102 newsize = ((iop->size - 2) * 2) + 2;
3104 /* Check for overflow */
3105 if (newsize <= iop->size)
3106 fatal(_("could not allocate more input memory"));
3108 /* Make sure there's room for a disk block */
3109 if (newsize - valid < iop->readsize)
3110 newsize += iop->readsize + 2;
3112 /* Check for overflow, again */
3113 if (newsize <= iop->size)
3114 fatal(_("could not allocate more input memory"));
3116 iop->size = newsize;
3117 erealloc(iop->buf, char *, iop->size, "grow_iop_buffer");
3118 iop->off = iop->buf + off;
3119 iop->dataend = iop->off + valid;
3120 iop->end = iop->buf + iop->size;
3123 /* Here are the routines. */
3125 /* rs1scan --- scan for a single character record terminator */
3128 rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
3137 memset(recm, '\0', sizeof(struct recmatch));
3139 *(iop->dataend) = rs; /* set sentinel */
3140 recm->start = iop->off; /* beginning of record */
3143 if (*state == INDATA) /* skip over data we've already seen */
3148 * From: Bruno Haible <bruno@clisp.org>
3149 * To: Aharon Robbins <arnold@skeeve.com>, gnits@gnits.org
3150 * Subject: Re: multibyte locales: any way to find if a character isn't multibyte?
3151 * Date: Mon, 23 Jun 2003 12:20:16 +0200
3152 * Cc: isamu@yamato.ibm.com
3156 * > Is there any way to make the following query to the current locale?
3158 * > Given an 8-bit value, can this value ever appear as part of
3159 * > a multibyte character?
3161 * There is no simple answer here. The easiest solution I see is to
3162 * get the current locale's codeset (via locale_charset() which is a
3163 * wrapper around nl_langinfo(CODESET)), and then perform a case-by-case
3164 * treatment of the known multibyte encodings, from GB2312 to EUC-JISX0213;
3165 * for the unibyte encodings, a single btowc() call will tell you.
3167 * > This is particularly critical for me for ASCII newline ('\n'). If I
3168 * > can be guaranteed that it never shows up as part of a multibyte character,
3169 * > I can speed up gawk considerably in mulitbyte locales.
3171 * This is much simpler to answer!
3172 * In all ASCII based multibyte encodings used for locales today (this
3173 * excludes EBCDIC based doublebyte encodings from IBM, and also excludes
3174 * ISO-2022-JP which is used for email exchange but not as a locale encoding)
3175 * ALL bytes in the range 0x00..0x2F occur only as a single character, not
3176 * as part of a multibyte character.
3178 * So it's safe to assume, but deserves a comment in the source.
3181 ***************************************************************
3182 * From: Bruno Haible <bruno@clisp.org>
3183 * To: Aharon Robbins <arnold@skeeve.com>
3184 * Subject: Re: multibyte locales: any way to find if a character isn't multibyte?
3185 * Date: Mon, 23 Jun 2003 14:27:49 +0200
3187 * On Monday 23 June 2003 14:11, you wrote:
3189 * > if (rs != '\n' && MB_CUR_MAX > 1) {
3191 * If you assume ASCII, you can even write
3193 * if (rs >= 0x30 && MB_CUR_MAX > 1) {
3195 * (this catches also the space character) but if portability to EBCDIC
3196 * systems is desired, your code is fine as is.
3200 /* Thus, the check for \n here; big speedup ! */
3201 if (rs != '\n' && gawk_mb_cur_max > 1) {
3202 int len = iop->dataend - bp;
3205 memset(& mbs, 0, sizeof(mbstate_t));
3209 if (is_valid_character(*bp))
3212 mbclen = mbrlen(bp, len, & mbs);
3214 || mbclen == (size_t) -1
3215 || mbclen == (size_t) -2
3217 /* We treat it as a single-byte character. */
3222 } while (len > 0 && ! found);
3224 /* Check that newline found isn't the sentinel. */
3225 if (found && (bp - mbclen) < iop->dataend) {
3227 * Set len to what we have so far, in case this is
3230 recm->len = bp - recm->start - mbclen;
3231 recm->rt_start = bp - mbclen;
3232 recm->rt_len = mbclen;
3237 recm->len = bp - recm->start;
3239 iop->scanoff = bp - iop->off;
3247 /* set len to what we have so far, in case this is all there is */
3248 recm->len = bp - recm->start;
3250 if (bp < iop->dataend) { /* found it in the buffer */
3251 recm->rt_start = bp;
3257 iop->scanoff = bp - iop->off;
3262 /* rsrescan --- search for a regex match in the buffer */
3265 rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
3268 size_t restart = 0, reend = 0;
3269 Regexp *RSre = RS_regexp;
3270 int regex_flags = RE_NEED_START;
3272 memset(recm, '\0', sizeof(struct recmatch));
3273 recm->start = iop->off;
3276 if (*state == INDATA)
3279 if ((iop->flag & IOP_AT_START) == 0)
3280 regex_flags |= RE_NO_BOL;
3282 /* case 1, no match */
3283 if (research(RSre, bp, 0, iop->dataend - bp, regex_flags) == -1) {
3284 /* set len, in case this all there is. */
3285 recm->len = iop->dataend - iop->off;
3289 /* ok, we matched within the buffer, set start and end */
3290 restart = RESTART(RSre, iop->off);
3291 reend = REEND(RSre, iop->off);
3293 /* case 2, null regex match, grow buffer, try again */
3294 if (restart == reend) {
3296 iop->scanoff = reend + 1;
3298 * If still room in buffer, skip over null match
3299 * and restart search. Otherwise, return.
3301 if (bp + iop->scanoff < iop->dataend) {
3305 recm->len = (bp - iop->off) + restart;
3310 * At this point, we have a non-empty match.
3312 * First, fill in rest of data. The rest of the cases return
3313 * a record and terminator.
3315 recm->len = restart;
3316 recm->rt_start = bp + restart;
3317 recm->rt_len = reend - restart;
3321 * 3. Match exactly at end:
3322 * if re is a simple string match
3323 * found a simple string match at end, return REC_OK
3325 * grow buffer, add more data, try again
3328 if (iop->off + reend >= iop->dataend) {
3329 if (reisstring(RS->stptr, RS->stlen, RSre, iop->off))
3336 * 4. Match within xxx bytes of end & maybe islong re:
3337 * return TERMNEAREND
3341 * case 4, match succeeded, but there may be more in
3342 * the next input buffer.
3344 * Consider an RS of xyz(abc)? where the
3345 * exact end of the buffer is xyza and the
3346 * next two, unread, characters are bc.
3348 * This matches the "xyz" and ends up putting the
3349 * "abc" into the front of the next record. Ooops.
3351 * The re->maybe_long member is true if the
3352 * regex contains one of: + * ? |. This is a very
3353 * simple heuristic, but in combination with the
3354 * "end of match within a few bytes of end of buffer"
3355 * check, should keep things reasonable.
3358 /* succession of tests is easier to trace in GDB. */
3359 if (RSre->maybe_long) {
3360 char *matchend = iop->off + reend;
3362 if (iop->dataend - matchend < RS->stlen)
3369 /* rsnullscan --- handle RS = "" */
3372 rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
3376 if (*state == NOSTATE || *state == INLEADER)
3377 memset(recm, '\0', sizeof(struct recmatch));
3379 recm->start = iop->off;
3382 if (*state != NOSTATE)
3386 *(iop->dataend) = '\n';
3388 if (*state == INTERM)
3389 goto find_longest_terminator;
3390 else if (*state == INDATA)
3393 fall into things from beginning,
3394 either NOSTATE or INLEADER */
3397 /* leading newlines are ignored */
3398 while (*bp == '\n' && bp < iop->dataend)
3401 if (bp >= iop->dataend) { /* LOTS of leading newlines, sheesh. */
3403 iop->scanoff = bp - iop->off;
3407 iop->off = recm->start = bp; /* real start of record */
3409 while (*bp++ != '\n')
3412 if (bp >= iop->dataend) { /* no full terminator */
3413 iop->scanoff = recm->len = bp - iop->off - 1;
3414 if (bp == iop->dataend) { /* half a terminator */
3415 recm->rt_start = bp - 1;
3422 /* found one newline before end of buffer, check next char */
3426 /* we've now seen at least two newlines */
3428 recm->len = bp - iop->off - 1;
3429 recm->rt_start = bp - 1;
3431 find_longest_terminator:
3432 /* find as many newlines as we can, to set RT */
3433 while (*bp == '\n' && bp < iop->dataend)
3436 recm->rt_len = bp - recm->rt_start;
3437 iop->scanoff = bp - iop->off;
3439 if (bp >= iop->dataend)
3446 * get_a_record --- read a record from IOP into out,
3447 * return length of EOF, set RT.
3448 * Note that errcode is never NULL, and the caller initializes *errcode to 0.
3452 get_a_record(char **out, /* pointer to pointer to data */
3453 IOBUF *iop, /* input IOP */
3454 int *errcode) /* pointer to error variable */
3456 struct recmatch recm;
3461 static RECVALUE (*lastmatchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = NULL;
3463 if (at_eof(iop) && no_data_left(iop))
3466 if (read_can_timeout)
3467 read_timeout = get_read_timeout(iop);
3469 if (iop->public.get_record != NULL) {
3472 int rc = iop->public.get_record(out, &iop->public, errcode,
3473 &rt_start, &rt_len);
3475 iop->flag |= IOP_AT_EOF;
3478 set_RT(rt_start, rt_len);
3485 /* fill initial buffer */
3486 if (has_no_data(iop) || no_data_left(iop)) {
3487 iop->count = iop->public.read_func(iop->public.fd, iop->buf, iop->readsize);
3488 if (iop->count == 0) {
3489 iop->flag |= IOP_AT_EOF;
3491 } else if (iop->count == -1) {
3492 iop->flag |= IOP_AT_EOF;
3496 iop->dataend = iop->buf + iop->count;
3497 iop->off = iop->buf;
3501 /* loop through file to find a record */
3508 ret = (*matchrec)(iop, & recm, & state);
3509 iop->flag &= ~IOP_AT_START;
3513 /* need to add more data to buffer */
3514 /* shift data down in buffer */
3515 dataend_off = iop->dataend - iop->off;
3516 memmove(iop->buf, iop->off, dataend_off);
3517 iop->off = iop->buf;
3518 iop->dataend = iop->buf + dataend_off;
3520 /* adjust recm contents */
3521 recm.start = iop->off;
3522 if (recm.rt_start != NULL)
3523 recm.rt_start = iop->off + recm.len;
3525 /* read more data, break if EOF */
3527 #define MIN(x, y) (x < y ? x : y)
3529 /* subtract one in read count to leave room for sentinel */
3530 room_left = iop->end - iop->dataend - 1;
3531 amt_to_read = MIN(iop->readsize, room_left);
3533 if (amt_to_read < iop->readsize) {
3534 grow_iop_buffer(iop);
3535 /* adjust recm contents */
3536 recm.start = iop->off;
3537 if (recm.rt_start != NULL)
3538 recm.rt_start = iop->off + recm.len;
3540 /* recalculate amt_to_read */
3541 room_left = iop->end - iop->dataend - 1;
3542 amt_to_read = MIN(iop->readsize, room_left);
3544 while (amt_to_read + iop->readsize < room_left)
3545 amt_to_read += iop->readsize;
3549 * POSIX limits read to SSIZE_MAX. There are (bizarre)
3550 * systems where this amount is small.
3552 amt_to_read = MIN(amt_to_read, SSIZE_MAX);
3555 iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read);
3556 if (iop->count == -1) {
3558 iop->flag |= IOP_AT_EOF;
3560 } else if (iop->count == 0) {
3562 * hit EOF before matching RS, so end
3563 * the record and set RT to ""
3565 iop->flag |= IOP_AT_EOF;
3568 iop->dataend += iop->count;
3571 /* set record, RT, return right value */
3574 * rtval is not a static pointer to avoid dangling pointer problems
3575 * in case awk code assigns to RT. A remote possibility, to be sure,
3576 * but Bitter Experience teaches us not to make ``that'll never
3577 * happen'' kinds of assumptions.
3579 rtval = RT_node->var_value;
3581 if (recm.rt_len == 0) {
3583 lastmatchrec = NULL;
3585 assert(recm.rt_start != NULL);
3587 * Optimization. For rs1 case, don't set RT if
3588 * character is same as last time. This knocks a
3589 * chunk of time off something simple like
3591 * gawk '{ print }' /some/big/file
3593 * Similarly, for rsnull case, if length of new RT is
3594 * shorter than current RT, just bump length down in RT.
3596 * Make sure that matchrec didn't change since the last
3597 * check. (Ugh, details, details, details.)
3599 if (lastmatchrec == NULL || lastmatchrec != matchrec) {
3600 lastmatchrec = matchrec;
3601 set_RT(recm.rt_start, recm.rt_len);
3602 } else if (matchrec == rs1scan) {
3603 if (rtval->stlen != 1 || rtval->stptr[0] != recm.rt_start[0])
3604 set_RT(recm.rt_start, recm.rt_len);
3607 } else if (matchrec == rsnullscan) {
3608 if (rtval->stlen >= recm.rt_len) {
3609 rtval->stlen = recm.rt_len;
3612 set_RT(recm.rt_start, recm.rt_len);
3614 set_RT(recm.rt_start, recm.rt_len);
3617 if (recm.len == 0) {
3621 assert(recm.start != NULL);
3626 iop->off += recm.len + recm.rt_len;
3628 if (recm.len == 0 && recm.rt_len == 0 && at_eof(iop))
3634 /* set_RS --- update things as appropriate when RS is set */
3639 static NODE *save_rs = NULL;
3642 * Don't use cmp_nodes(), which pays attention to IGNORECASE.
3645 && RS_node->var_value->stlen == save_rs->stlen
3646 && memcmp(RS_node->var_value->stptr, save_rs->stptr, save_rs->stlen) == 0) {
3648 * It could be that just IGNORECASE changed. If so,
3649 * update the regex and then do the same for FS.
3650 * set_IGNORECASE() relies on this routine to call
3653 RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case);
3657 save_rs = dupnode(RS_node->var_value);
3659 RS = force_string(RS_node->var_value);
3661 * used to be if (RS_regexp != NULL) { refree(..); refree(..); ...; }.
3662 * Please do not remerge the if condition; hinders memory deallocation
3663 * in case of fatal error in make_regexp.
3665 refree(RS_re_yes_case); /* NULL argument is ok */
3666 refree(RS_re_no_case);
3667 RS_re_yes_case = RS_re_no_case = RS_regexp = NULL;
3669 if (RS->stlen == 0) {
3671 matchrec = rsnullscan;
3672 } else if (RS->stlen > 1) {
3673 static bool warned = false;
3675 RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, false, true, true);
3676 RS_re_no_case = make_regexp(RS->stptr, RS->stlen, true, true, true);
3677 RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case);
3679 matchrec = rsrescan;
3681 if (do_lint && ! warned) {
3682 lintwarn(_("multicharacter value of `RS' is a gawk extension"));
3688 if (current_field_sep() == Using_FS)
3693 /* pty_vs_pipe --- return true if should use pty instead of pipes for `|&' */
3696 * This works by checking if PROCINFO["command", "pty"] exists and is true.
3700 pty_vs_pipe(const char *command)
3702 #ifdef HAVE_TERMIOS_H
3705 if (PROCINFO_node == NULL)
3707 val = in_PROCINFO(command, "pty", NULL);
3709 if ((val->flags & MAYBE_NUM) != 0)
3710 (void) force_number(val);
3711 if ((val->flags & NUMBER) != 0)
3712 return ! iszero(val);
3714 return (val->stlen != 0);
3716 #endif /* HAVE_TERMIOS_H */
3720 /* iopflags2str --- make IOP flags printable */
3723 iopflags2str(int flag)
3725 static const struct flagtab values[] = {
3726 { IOP_IS_TTY, "IOP_IS_TTY" },
3727 { IOP_AT_EOF, "IOP_AT_EOF" },
3728 { IOP_CLOSED, "IOP_CLOSED" },
3729 { IOP_AT_START, "IOP_AT_START" },
3733 return genflags2str(flag, values);
3736 /* free_rp --- release the memory used by rp */
3739 free_rp(struct redirect *rp)
3745 /* inetfile --- return true for a /inet special file, set other values */
3748 inetfile(const char *str, int *length, int *family)
3752 if (strncmp(str, "/inet/", 6) == 0) {
3757 *family = AF_UNSPEC;
3758 } else if (strncmp(str, "/inet4/", 7) == 0) {
3764 } else if (strncmp(str, "/inet6/", 7) == 0) {
3770 #ifndef HAVE_GETADDRINFO
3771 fatal(_("IPv6 communication is not supported"));
3779 * in_PROCINFO --- return value for a PROCINFO element with
3780 * SUBSEP seperated indices.
3784 in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
3788 NODE *r, *sub = NULL;
3789 NODE *subsep = SUBSEP_node->var_value;
3791 /* full_idx is in+out parameter */
3796 str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2);
3798 emalloc(str, char *, str_len + 1, "in_PROCINFO");
3799 sub = make_str_node(str, str_len, ALREADY_MALLOCED);
3802 } else if (str_len != sub->stlen) {
3803 /* *full_idx != NULL */
3805 assert(sub->valref == 1);
3806 erealloc(sub->stptr, char *, str_len + 1, "in_PROCINFO");
3807 sub->stlen = str_len;
3810 sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen,
3811 subsep->stptr, pidx2);
3812 r = in_array(PROCINFO_node, sub);
3819 /* get_read_timeout --- get timeout in milliseconds for reading */
3822 get_read_timeout(IOBUF *iop)
3826 if (PROCINFO_node != NULL) {
3827 const char *name = iop->public.name;
3829 static NODE *full_idx = NULL;
3830 static const char *last_name = NULL;
3833 * Do not re-construct the full index when last redirection
3834 * string is the same as the current; "efficiency_hack++".
3836 if (full_idx == NULL || strcmp(name, last_name) != 0) {
3837 val = in_PROCINFO(name, "READ_TIMEOUT", & full_idx);
3838 if (last_name != NULL)
3839 efree((void *) last_name);
3840 last_name = estrdup(name, strlen(name));
3841 } else /* use cached full index */
3842 val = in_array(PROCINFO_node, full_idx);
3845 (void) force_number(val);
3846 tmout = get_number_si(val);
3849 tmout = read_default_timeout; /* initialized from env. variable in init_io() */
3851 /* overwrite read routine only if an extension has not done so */
3852 if ((iop->public.read_func == ( ssize_t(*)() ) read) && tmout > 0)
3853 iop->public.read_func = read_with_timeout;
3859 * read_with_timeout --- read with a timeout, return failure
3860 * if no data is available within the timeout period.
3864 read_with_timeout(int fd, char *buf, size_t size)
3871 * Only sockets can be read with a timeout. Also, the FD_*
3872 * macros work on SOCKET type, not on int file descriptors.
3874 SOCKET s = valid_socket(fd);
3877 return read(fd, buf, size);
3882 tv.tv_sec = read_timeout / 1000;
3883 tv.tv_usec = 1000 * (read_timeout - 1000 * tv.tv_sec);
3886 FD_SET(s, & readfds);
3890 * Note: the 1st arg of 'select' is ignored on MS-Windows, so
3891 * it's not a mistake to pass fd+1 there, although we use
3892 * sockets, not file descriptors.
3894 if (select(fd + 1, & readfds, NULL, NULL, & tv) < 0)
3897 if (FD_ISSET(s, & readfds))
3898 return read(fd, buf, size);
3902 /* Set a meaningful errno */
3910 return read(fd, buf, size);
3915 * Dummy pass through functions for default output.
3918 /* gawk_fwrite --- like fwrite */
3921 gawk_fwrite(const void *buf, size_t size, size_t count, FILE *fp, void *opaque)
3925 return fwrite(buf, size, count, fp);
3929 gawk_fflush(FILE *fp, void *opaque)
3937 gawk_ferror(FILE *fp, void *opaque)
3945 gawk_fclose(FILE *fp, void *opaque)
3949 SOCKET s = valid_socket (fileno(fp));
3953 result = fclose(fp);
3955 if (s && closesocket(s) == SOCKET_ERROR)
3962 /* init_output_wrapper --- initialize the output wrapper */
3965 init_output_wrapper(awk_output_buf_t *outbuf)
3967 outbuf->name = NULL;
3968 outbuf->mode = NULL;
3970 outbuf->opaque = NULL;
3971 outbuf->redirected = awk_false;
3972 outbuf->gawk_fwrite = gawk_fwrite;
3973 outbuf->gawk_fflush = gawk_fflush;
3974 outbuf->gawk_ferror = gawk_ferror;
3975 outbuf->gawk_fclose = gawk_fclose;