Update spec to require automake >= 1.13
[platform/upstream/gawk.git] / io.c
1 /*
2  * io.c --- routines for dealing with input and output and records
3  */
4
5 /* 
6  * Copyright (C) 1986, 1988, 1989, 1991-2014 the Free Software Foundation, Inc.
7  * 
8  * This file is part of GAWK, the GNU implementation of the
9  * AWK Programming Language.
10  * 
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.
15  * 
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.
20  * 
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
24  */
25
26 /* For OSF/1 to get struct sockaddr_storage */
27 #if defined(__osf__) && !defined(_OSF_SOURCE)
28 #define _OSF_SOURCE
29 #endif
30
31 #include "awk.h"
32
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 */
40
41 #ifndef O_ACCMODE
42 #define O_ACCMODE       (O_RDONLY|O_WRONLY|O_RDWR)
43 #endif
44
45 #if ! defined(S_ISREG) && defined(S_IFREG)
46 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
47 #endif
48
49 #ifdef HAVE_TERMIOS_H
50 #include <termios.h>
51 #endif
52 #ifdef HAVE_STROPTS_H
53 #include <stropts.h>
54 #endif
55
56 #ifdef HAVE_SOCKETS
57
58 #ifdef HAVE_SYS_SOCKET_H
59 #include <sys/socket.h>
60 #else
61 #include <socket.h>
62 #endif /* HAVE_SYS_SOCKET_H */
63
64 #ifdef HAVE_NETINET_IN_H
65 #include <netinet/in.h>
66
67 #ifdef HAVE_ARPA_INET_H
68 #include <arpa/inet.h>
69 #endif
70
71 #else /* ! HAVE_NETINET_IN_H */
72 #include <in.h>
73 #endif /* HAVE_NETINET_IN_H */
74
75 #ifdef HAVE_NETDB_H
76 #include <netdb.h>
77 #endif /* HAVE_NETDB_H */
78
79 #ifndef HAVE_GETADDRINFO
80 #include "missing_d/getaddrinfo.h"
81 #endif
82
83 #ifndef AI_ADDRCONFIG   /* not everyone has this symbol */
84 #define AI_ADDRCONFIG 0
85 #endif /* AI_ADDRCONFIG */
86
87 #ifndef HAVE_SOCKADDR_STORAGE
88 #define sockaddr_storage sockaddr       /* for older systems */
89 #endif /* HAVE_SOCKADDR_STORAGE */
90
91 #endif /* HAVE_SOCKETS */
92
93 #ifndef AF_UNSPEC
94 #define AF_UNSPEC 0
95 #endif
96 #ifndef AF_INET
97 #define AF_INET 2
98 #endif
99 #ifndef AF_INET6
100 #define AF_INET6 10
101 #endif
102
103 #ifdef HAVE_LIMITS_H
104 #include <limits.h>
105 #endif
106
107 #if defined(HAVE_POPEN_H)
108 #include "popen.h"
109 #endif
110
111 #ifdef __EMX__
112 #include <process.h>
113 #endif
114
115 #ifndef ENFILE
116 #define ENFILE EMFILE
117 #endif
118
119 #if defined(__DJGPP__)
120 #define closemaybesocket(fd)    close(fd)
121 #endif
122
123 #if defined(VMS)
124 #include <ssdef.h>
125 #ifndef SS$_EXBYTLM
126 #define SS$_EXBYTLM 0x2a14  /* VMS 8.4 seen */
127 #endif
128 #include <rmsdef.h>
129 #define closemaybesocket(fd)    close(fd)
130 #endif
131
132 #ifdef HAVE_SOCKETS
133
134 #ifndef SHUT_RD
135 # ifdef SD_RECEIVE
136 #  define SHUT_RD       SD_RECEIVE
137 # else
138 #  define SHUT_RD       0
139 # endif
140 #endif
141
142 #ifndef SHUT_WR
143 # ifdef SD_SEND
144 #  define SHUT_WR       SD_SEND
145 # else
146 #  define SHUT_WR       1
147 # endif
148 #endif
149
150 #ifndef SHUT_RDWR
151 # ifdef SD_BOTH
152 #  define SHUT_RDWR     SD_BOTH
153 # else
154 #  define SHUT_RDWR     2
155 # endif
156 #endif
157
158 /* MinGW defines non-trivial macros on pc/socket.h.  */
159 #ifndef FD_TO_SOCKET
160 # define FD_TO_SOCKET(fd)       (fd)
161 # define closemaybesocket(fd)   close(fd)
162 #endif
163
164 #ifndef SOCKET_TO_FD
165 # define SOCKET_TO_FD(s)        (s)
166 # define SOCKET                 int
167 #endif
168
169 #endif /* HAVE_SOCKETS */
170
171 #ifndef HAVE_SETSID
172 #define setsid()        /* nothing */
173 #endif /* HAVE_SETSID */
174
175 #if defined(GAWK_AIX)
176 #undef TANDEM   /* AIX defines this in one of its header files */
177 #endif
178
179 #ifdef __DJGPP__
180 #define PIPES_SIMULATED
181 #endif
182
183 #ifdef __MINGW32__
184 # ifndef PIPES_SIMULATED
185 #  define pipe(fds)     _pipe(fds, 0, O_NOINHERIT)
186 # endif
187 #endif
188
189 #ifdef HAVE_MPFR
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++
193 #else
194 #define INCREMENT_REC(X)        X++
195 #endif
196
197 typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
198
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)
203
204 /*
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
210  * value:
211  */
212
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
219                            the file. */
220 } RECVALUE;
221
222 /*
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.
226  */
227
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) */
233 } SCANSTATE;
234
235 /*
236  * When a record is seen (REC_OK or TERMATEND), the following
237  * structure is filled in.
238  */
239
240 struct recmatch {
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 */
245 };
246
247
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);
254 #endif
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);
266
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);
270
271 static RECVALUE (*matchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = rs1scan;
272
273 static int get_a_record(char **out, IOBUF *iop, int *errcode);
274
275 static void free_rp(struct redirect *rp);
276 static int inetfile(const char *str, int *length, int *family);
277
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);
281
282 static bool read_can_timeout = false;
283 static long read_timeout;
284 static long read_default_timeout;
285
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;
291
292 bool RS_is_null;
293
294 extern NODE *ARGC_node;
295 extern NODE *ARGV_node;
296 extern NODE *ARGIND_node;
297 extern NODE **fields_arr;
298
299 /* init_io --- set up timeout related variables */
300
301 void
302 init_io()
303 {
304         long tmout;
305
306         /* Only MinGW has a non-trivial implementation of this.  */
307         init_sockets();
308
309         /*
310          * N.B.: all these hacks are to minimize the effect
311          * on programs that do not care about timeout.
312          */
313
314         /* Parse the env. variable only once */
315         tmout = getenv_long("GAWK_READ_TIMEOUT");
316         if (tmout > 0) {
317                 read_default_timeout = tmout;
318                 read_can_timeout = true;
319         }
320
321         /*
322          * PROCINFO entries for timeout are dynamic;
323          * We can't be any more specific than this.
324          */
325         if (PROCINFO_node != NULL)      
326                 read_can_timeout = true;
327 }
328
329
330 #if defined(__DJGPP__) || defined(__MINGW32__) || defined(__EMX__) || defined(__CYGWIN__)
331 /* binmode --- convert BINMODE to string for fopen */
332
333 static const char *
334 binmode(const char *mode)
335 {
336         switch (mode[0]) {
337         case 'r':
338                 if ((BINMODE & BINMODE_INPUT) != 0)
339                         mode = "rb";
340                 break;
341         case 'w':
342         case 'a':
343                 if ((BINMODE & BINMODE_OUTPUT) != 0)
344                         mode = (mode[0] == 'w' ? "wb" : "ab");
345                 break;
346         }
347         return mode;
348 }
349 #else
350 #define binmode(mode)   (mode)
351 #endif
352
353 #ifdef VMS
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); }
358 #undef fileno
359 #define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1)
360 #endif  /* VMS */
361
362 /* after_beginfile --- reset necessary state after BEGINFILE has run */
363
364 void
365 after_beginfile(IOBUF **curfile)
366 {
367         IOBUF *iop;
368
369         iop = *curfile;
370         assert(iop != NULL);
371
372         /*
373          * Input parsers could have been changed by BEGINFILE,
374          * so delay check until now.
375          */
376
377         find_input_parser(iop);
378
379         if (! iop->valid) {
380                 const char *fname;
381                 int errcode;
382                 bool valid;
383
384                 fname = iop->public.name;
385                 errcode = iop->errcode; 
386                 valid = iop->valid;
387                 errno = 0;
388                 update_ERRNO_int(errcode);
389                 iop_close(iop);
390                 *curfile = NULL;
391                 if (! valid && errcode == EISDIR && ! do_traditional) {
392                         warning(_("command line argument `%s' is a directory: skipped"), fname);
393                         return;         /* read next file */
394                 }
395                 fatal(_("cannot open file `%s' for reading (%s)"),
396                                 fname, strerror(errcode));
397         }
398 }
399
400 /* nextfile --- move to the next input data file */
401 /*
402  * Return value > 0 ----> run BEGINFILE block
403  * *curfile = NULL  ----> hit EOF, run ENDFILE block
404  */
405
406 int
407 nextfile(IOBUF **curfile, bool skipping)
408 {
409         static long i = 1;
410         static bool files = false;
411         NODE *arg, *tmp;
412         const char *fname;
413         int fd = INVALID_HANDLE;
414         int errcode = 0;
415         IOBUF *iop = *curfile;
416         long argc;
417
418         if (skipping) {                 /* for 'nextfile' call */
419                 errcode = 0;
420                 if (iop != NULL) {
421                         errcode = iop->errcode;
422                         (void) iop_close(iop);
423                 }
424                 *curfile = NULL;
425                 return (errcode == 0);
426         }
427
428         if (iop != NULL) {
429                 if (at_eof(iop)) {
430                         assert(iop->public.fd != INVALID_HANDLE);
431                         (void) iop_close(iop);
432                         *curfile = NULL;
433                         return 1;       /* run endfile block */
434                 } else                          
435                         return 0;
436         }
437
438         argc = get_number_si(ARGC_node->var_value);
439         
440         for (; i < argc; i++) {
441                 tmp = make_number((AWKNUM) i);
442                 (void) force_string(tmp);
443                 arg = in_array(ARGV_node, tmp);
444                 unref(tmp);
445                 if (arg == NULL || arg->stlen == 0)
446                         continue;
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);
452                 }
453
454                 if (! arg_assign(arg->stptr, false)) {
455                         files = true;
456                         fname = arg->stptr;
457
458                         /* manage the awk variables: */
459                         unref(FILENAME_node->var_value);
460                         FILENAME_node->var_value = dupnode(arg);
461 #ifdef HAVE_MPFR
462                         if (is_mpg_number(FNR_node->var_value))
463                                 mpz_set_ui(MFNR, 0);
464 #endif
465                         FNR = 0;
466
467                         /* IOBUF management: */
468                         errno = 0;
469                         fd = devopen(fname, binmode("r"));
470                         if (fd == INVALID_HANDLE && errno == EMFILE) {
471                                 close_one();
472                                 close_one();
473                                 fd = devopen(fname, binmode("r"));
474                         }
475                         errcode = errno;
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;
482                         else if (iop->valid)
483                                 iop->errcode = 0;
484
485                         if (! do_traditional && iop->errcode != 0)
486                                 update_ERRNO_int(iop->errcode);
487
488                         return ++i;     /* run beginfile block */
489                 }
490         }
491
492         if (files == false) {
493                 files = true;
494                 /* no args. -- use stdin */
495                 /* FNR is init'ed to 0 */
496                 errno = 0;
497                 if (! do_traditional)
498                         update_ERRNO_int(errno);
499
500                 unref(FILENAME_node->var_value);
501                 FILENAME_node->var_value = make_string("-", 1);
502                 FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */
503                 fname = "-";
504                 iop = iop_alloc(fileno(stdin), fname, 0);
505                 *curfile = iop_finish(iop);
506
507                 if (iop->public.fd == INVALID_HANDLE) {
508                         errcode = errno;
509                         errno = 0;
510                         update_ERRNO_int(errno);
511                         (void) iop_close(iop);
512                         *curfile = NULL;
513                         fatal(_("cannot open file `%s' for reading (%s)"),
514                                         fname, strerror(errcode));
515                 }
516                 return ++i;     /* run beginfile block */
517         }
518
519         return -1;      /* end of input, run end block or Op_atexit */
520 }
521
522 /* set_FNR --- update internal FNR from awk variable */
523
524 void
525 set_FNR()
526 {
527         NODE *n = FNR_node->var_value;
528         (void) force_number(n);
529 #ifdef HAVE_MPFR
530         if (is_mpg_number(n))
531                 FNR = mpg_set_var(FNR_node);
532         else
533 #endif
534         FNR = get_number_si(n);
535 }
536
537 /* set_NR --- update internal NR from awk variable */
538
539 void
540 set_NR()
541 {
542         NODE *n = NR_node->var_value;
543         (void) force_number(n);
544 #ifdef HAVE_MPFR
545         if (is_mpg_number(n))
546                 NR = mpg_set_var(NR_node);
547         else
548 #endif
549         NR = get_number_si(n);
550 }
551
552 /* inrec --- This reads in a record from the input file */
553
554 int
555 inrec(IOBUF *iop, int *errcode)
556 {
557         char *begin;
558         int cnt;
559         int retval = 0;
560
561         if (at_eof(iop) && no_data_left(iop))
562                 cnt = EOF;
563         else if ((iop->flag & IOP_CLOSED) != 0)
564                 cnt = EOF;
565         else 
566                 cnt = get_a_record(& begin, iop, errcode);
567
568         if (cnt == EOF) {
569                 retval = 1;
570                 if (*errcode > 0)
571                         update_ERRNO_int(*errcode);
572         } else {
573                 INCREMENT_REC(NR);
574                 INCREMENT_REC(FNR);
575                 set_record(begin, cnt);
576         }
577
578         return retval;
579 }
580
581 /* remap_std_file --- reopen a standard descriptor on /dev/null */
582
583 static int
584 remap_std_file(int oldfd)
585 {
586         int newfd;
587         int ret = -1;
588
589         /*
590          * Give OS-specific routines in gawkmisc.c a chance to interpret
591          * "/dev/null" as appropriate for their platforms.
592          */
593         newfd = os_devopen("/dev/null", O_RDWR);
594         if (newfd == INVALID_HANDLE)
595                 newfd = open("/dev/null", O_RDWR);
596         if (newfd >= 0) {
597                 /* if oldfd is open, dup2() will close oldfd for us first. */
598                 ret = dup2(newfd, oldfd);
599                 if (ret == 0)
600                         close(newfd);
601         } else
602                 ret = 0;
603
604         return ret;
605 }
606
607 /* iop_close --- close an open IOP */
608
609 static int
610 iop_close(IOBUF *iop)
611 {
612         int ret = 0;
613
614         if (iop == NULL)
615                 return 0;
616
617         errno = 0;
618
619         iop->flag &= ~IOP_AT_EOF;
620         iop->flag |= IOP_CLOSED;        /* there may be dangling pointers */
621         iop->dataend = NULL;
622         /*
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.
626          */
627         if (iop->public.close_func != NULL)
628                 iop->public.close_func(&iop->public);
629
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);
635                 else
636                         ret = closemaybesocket(iop->public.fd);
637         }
638
639         if (ret == -1)
640                 warning(_("close of fd %d (`%s') failed (%s)"), iop->public.fd,
641                                 iop->public.name, strerror(errno));
642         /*
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.
646          */
647         if (iop->buf) {
648                 if ((fields_arr[0]->stptr >= iop->buf)
649                     && (fields_arr[0]->stptr < (iop->buf + iop->size))) {
650                         NODE *t;
651
652                         t = make_string(fields_arr[0]->stptr,
653                                         fields_arr[0]->stlen);
654                         unref(fields_arr[0]);
655                         fields_arr[0] = t;
656                         /*
657                          * This used to be here:
658                          *
659                          * reset_record();
660                          *
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.
664                          */
665                 }
666                 efree(iop->buf);
667                 iop->buf = NULL;
668         }
669         efree(iop);
670         return ret == -1 ? 1 : 0;
671 }
672
673 /* redflags2str --- turn redirection flags into a string, for debugging */
674
675 const char *
676 redflags2str(int flags)
677 {
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" },
690                 { 0, NULL }
691         };
692
693         return genflags2str(flags, redtab);
694 }
695
696 /* redirect --- Redirection for printf and print commands */
697
698 struct redirect *
699 redirect(NODE *redir_exp, int redirtype, int *errflg)
700 {
701         struct redirect *rp;
702         char *str;
703         int tflag = 0;
704         int outflag = 0;
705         const char *direction = "to";
706         const char *mode;
707         int fd;
708         const char *what = NULL;
709         bool new_rp = false;
710         int len;        /* used with /inet */
711         static struct redirect *save_rp = NULL; /* hold onto rp that should
712                                                  * be freed for reuse
713                                                  */
714
715         if (do_sandbox)
716                 fatal(_("redirection not allowed in sandbox mode"));
717
718         switch (redirtype) {
719         case redirect_append:
720                 tflag = RED_APPEND;
721                 /* FALL THROUGH */
722         case redirect_output:
723                 outflag = (RED_FILE|RED_WRITE);
724                 tflag |= outflag;
725                 if (redirtype == redirect_output)
726                         what = ">";
727                 else
728                         what = ">>";
729                 break;
730         case redirect_pipe:
731                 tflag = (RED_PIPE|RED_WRITE);
732                 what = "|";
733                 break;
734         case redirect_pipein:
735                 tflag = (RED_PIPE|RED_READ);
736                 what = "|";
737                 break;
738         case redirect_input:
739                 tflag = (RED_FILE|RED_READ);
740                 what = "<";
741                 break;
742         case redirect_twoway:
743                 tflag = (RED_READ|RED_WRITE|RED_TWOWAY);
744                 what = "|&";
745                 break;
746         default:
747                 cant_happen();
748         }
749         if (do_lint && (redir_exp->flags & STRCUR) == 0)
750                 lintwarn(_("expression in `%s' redirection only has numeric value"),
751                         what);
752         redir_exp = force_string(redir_exp);
753         str = redir_exp->stptr;
754
755         if (str == NULL || *str == '\0')
756                 fatal(_("expression for `%s' redirection has null string value"),
757                         what);
758
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"),
762                                 str, what);
763
764 #ifdef HAVE_SOCKETS
765         /*
766          * Use /inet4 to force IPv4, /inet6 to force IPv6, and plain
767          * /inet will be whatever we get back from the system.
768          */
769         if (inetfile(str, & len, NULL)) {
770                 tflag |= RED_SOCKET;
771                 if (strncmp(str + len, "tcp/", 4) == 0)
772                         tflag |= RED_TCP;       /* use shutdown when closing */
773         }
774 #endif /* HAVE_SOCKETS */
775
776         for (rp = red_head; rp != NULL; rp = rp->next) {
777 #ifndef PIPES_SIMULATED
778                 /*
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.
785                  */
786                 if ((rp->flag & RED_EOF) != 0 && redirtype == redirect_pipein) {
787                         if (rp->pid != -1)
788 #ifdef __MINGW32__
789                                 /* MinGW cannot wait for any process.  */
790                                 wait_any(rp->pid);
791 #else
792                                 wait_any(0);
793 #endif
794                 }
795 #endif /* PIPES_SIMULATED */
796
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
801                         || (outflag != 0
802                             && (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) {
803
804                         int rpflag = (rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY));
805                         int newflag = (tflag & ~(RED_NOBUF|RED_EOF|RED_PTY));
806
807                         if (do_lint && rpflag != newflag)
808                                 lintwarn(
809                 _("unnecessary mixing of `>' and `>>' for file `%.*s'"),
810                                         (int) redir_exp->stlen, rp->value);
811
812                         break;
813                 }
814         }
815
816         if (rp == NULL) {
817                 new_rp = true;
818                 if (save_rp != NULL) {
819                         rp = save_rp;
820                         efree(rp->value);
821                 } else
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';
826                 rp->value = str;
827                 rp->flag = tflag;
828                 init_output_wrapper(& rp->output);
829                 rp->output.name = str;
830                 rp->iop = NULL;
831                 rp->pid = -1;
832                 rp->status = 0;
833         } else
834                 str = rp->value;        /* get \0 terminated string */
835         save_rp = rp;
836
837         while (rp->output.fp == NULL && rp->iop == NULL) {
838                 if (! new_rp && (rp->flag & RED_EOF) != 0) {
839                         /*
840                          * Encountered EOF on file or pipe -- must be cleared
841                          * by explicit close() before reading more
842                          */
843                         save_rp = NULL;
844                         return rp;
845                 }
846                 mode = NULL;
847                 errno = 0;
848                 switch (redirtype) {
849                 case redirect_output:
850                         mode = binmode("w");
851                         if ((rp->flag & RED_USED) != 0)
852                                 mode = (rp->mode[1] == 'b') ? "ab" : "a";
853                         break;
854                 case redirect_append:
855                         mode = binmode("a");
856                         break;
857                 case redirect_pipe:
858                         /* synchronize output before new pipe */
859                         (void) flush_io();
860
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));
865
866                         /* set close-on-exec */
867                         os_close_on_exec(fileno(rp->output.fp), str, "pipe", "to");
868                         rp->flag |= RED_NOBUF;
869                         break;
870                 case redirect_pipein:
871                         direction = "from";
872                         if (gawk_popen(str, rp) == NULL)
873                                 fatal(_("can't open pipe `%s' for input (%s)"),
874                                         str, strerror(errno));
875                         break;
876                 case redirect_input:
877                         direction = "from";
878                         fd = devopen(str, binmode("r"));
879                         if (fd == INVALID_HANDLE && errno == EISDIR) {
880                                 *errflg = EISDIR;
881                                 /* do not free rp, saving it for reuse (save_rp = rp) */
882                                 return NULL;
883                         }
884                         rp->iop = iop_alloc(fd, str, errno);
885                         find_input_parser(rp->iop);
886                         iop_finish(rp->iop);
887                         if (! rp->iop->valid) {
888                                 if (! do_traditional && rp->iop->errcode != 0)
889                                         update_ERRNO_int(rp->iop->errcode);
890                                 iop_close(rp->iop);
891                                 rp->iop = NULL;
892                         }
893                         break;
894                 case redirect_twoway:
895                         direction = "to/from";
896                         if (! two_way_open(str, rp)) {
897 #ifdef HAVE_SOCKETS
898                                 if (inetfile(str, NULL, NULL)) {
899                                         *errflg = errno;
900                                         /* do not free rp, saving it for reuse (save_rp = rp) */
901                                         return NULL;
902                                 } else
903 #endif
904                                         fatal(_("can't open two way pipe `%s' for input/output (%s)"),
905                                                         str, strerror(errno));
906                         }
907                         break;
908                 default:
909                         cant_happen();
910                 }
911
912                 if (mode != NULL) {
913                         errno = 0;
914                         rp->output.mode = mode;
915                         fd = devopen(str, mode);
916
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;
924                                 else {
925                                         const char *omode = mode;
926 #if defined(F_GETFL) && defined(O_APPEND)
927                                         int fd_flags;
928
929                                         fd_flags = fcntl(fd, F_GETFL);
930                                         if (fd_flags != -1 && (fd_flags & O_APPEND) == O_APPEND)
931                                                 omode = binmode("a");
932 #endif
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)
938                                                 close(fd);
939                                 }
940                                 if (rp->output.fp != NULL && os_isatty(fd))
941                                         rp->flag |= RED_NOBUF;
942
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;
947                                         red_head->prev = rp;
948                                         rp->prev = NULL;
949                                         rp->next = red_head;
950                                         red_head = rp;
951                                 }
952                         }
953                         find_output_wrapper(& rp->output);
954                 }
955
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)
959                                 close_one();
960 #ifdef VMS
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))
968                                 close_one();
969 #endif
970                         else {
971                                 /*
972                                  * Some other reason for failure.
973                                  *
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.
979                                  */
980                                 if (errflg != NULL)
981                                         *errflg = errno;
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));
988                                         else
989                                                 fatal(_("can't redirect to `%s' (%s)"),
990                                                         str, strerror(errno));
991                                 } else {
992                                         /* do not free rp, saving it for reuse (save_rp = rp) */
993                                         return NULL;
994                                 }
995                         }
996                 }
997         }
998
999         if (new_rp) {
1000                 /*
1001                  * It opened successfully, hook it into the list.
1002                  * Maintain the list in most-recently-used first order.
1003                  */
1004                 if (red_head != NULL)
1005                         red_head->prev = rp;
1006                 rp->prev = NULL;
1007                 rp->next = red_head;
1008                 red_head = rp;
1009         }
1010         save_rp = NULL;
1011         return rp;
1012 }
1013
1014 /* getredirect --- find the struct redirect for this file or pipe */
1015
1016 struct redirect *
1017 getredirect(const char *str, int len)
1018 {
1019         struct redirect *rp;
1020
1021         for (rp = red_head; rp != NULL; rp = rp->next)
1022                 if (strlen(rp->value) == len && memcmp(rp->value, str, len) == 0)
1023                         return rp;
1024
1025         return NULL;
1026 }
1027
1028 /* close_one --- temporarily close an open file to re-use the fd */
1029
1030 static void
1031 close_one()
1032 {
1033         struct redirect *rp;
1034         struct redirect *rplast = NULL;
1035
1036         static bool warned = false;
1037
1038         if (do_lint && ! warned) {
1039                 warned = true;
1040                 lintwarn(_("reached system limit for open files: starting to multiplex file descriptors"));
1041         }
1042
1043         /* go to end of list first, to pick up least recently used entry */
1044         for (rp = red_head; rp != NULL; rp = rp->next)
1045                 rplast = rp;
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)
1050                         continue;
1051
1052                 if ((rp->flag & (RED_FILE|RED_WRITE)) == (RED_FILE|RED_WRITE)) {
1053                         rp->flag |= RED_USED;
1054                         errno = 0;
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;
1059                         break;
1060                 }
1061         }
1062         if (rp == NULL)
1063                 /* surely this is the only reason ??? */
1064                 fatal(_("too many pipes or input files open")); 
1065 }
1066
1067 /* do_close --- completely close an open file or pipe */
1068
1069 NODE *
1070 do_close(int nargs)
1071 {
1072         NODE *tmp, *tmp2;
1073         struct redirect *rp;
1074         two_way_close_type how = CLOSE_ALL;     /* default */
1075
1076         if (nargs == 2) {
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)
1081                         how = CLOSE_TO;
1082                 else if (strcasecmp(tmp2->stptr, "from") == 0)
1083                         how = CLOSE_FROM;
1084                 else {
1085                         DEREF(tmp2);
1086                         fatal(_("close: second argument must be `to' or `from'"));
1087                 }
1088                 DEREF(tmp2);
1089         }
1090
1091         tmp = POP_STRING();     /* 1st arg: redir to close */
1092
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)
1096                         break;
1097         }
1098
1099         if (rp == NULL) {       /* no match, return -1 */
1100                 char *cp;
1101
1102                 if (do_lint)
1103                         lintwarn(_("close: `%.*s' is not an open file, pipe or co-process"),
1104                                 (int) tmp->stlen, tmp->stptr);
1105
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);
1110                 }
1111
1112                 DEREF(tmp);
1113                 return make_number((AWKNUM) -1.0);
1114         }
1115         DEREF(tmp);
1116         fflush(stdout); /* synchronize regular output */
1117         tmp = make_number((AWKNUM) close_redir(rp, false, how));
1118         rp = NULL;
1119         /*
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.
1124          */
1125         if (do_posix) {
1126                 unref(tmp);
1127                 tmp = make_number((AWKNUM) 0);
1128         }
1129         return tmp;
1130 }
1131
1132 /* close_rp --- separate function to just do closing */
1133
1134 static int
1135 close_rp(struct redirect *rp, two_way_close_type how)
1136 {
1137         int status = 0;
1138
1139         errno = 0;
1140         if ((rp->flag & RED_TWOWAY) != 0) {     /* two-way pipe */
1141                 /* write end: */
1142                 if ((how == CLOSE_ALL || how == CLOSE_TO) && rp->output.fp != NULL) {
1143 #ifdef HAVE_SOCKETS
1144                         if ((rp->flag & RED_TCP) != 0)
1145                                 (void) shutdown(fileno(rp->output.fp), SHUT_WR);
1146 #endif /* HAVE_SOCKETS */
1147
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);
1151                         }
1152                         status = rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1153                         rp->output.fp = NULL;
1154                 }
1155
1156                 /* read end: */
1157                 if (how == CLOSE_ALL || how == CLOSE_FROM) {
1158                         if ((rp->flag & RED_SOCKET) != 0 && rp->iop != NULL) {
1159 #ifdef HAVE_SOCKETS
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);
1164                         } else
1165                                 status = gawk_pclose(rp);
1166
1167                         rp->iop = NULL;
1168                 }
1169         } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) {
1170                 /* write to pipe */
1171                 status = pclose(rp->output.fp);
1172                 if ((BINMODE & BINMODE_INPUT) != 0)
1173                         os_setbinmode(fileno(stdin), O_BINARY);
1174
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);
1185                         rp->iop = NULL;
1186                 }
1187         }
1188
1189         return status;
1190 }
1191
1192 /* close_redir --- close an open file or pipe */
1193
1194 static int
1195 close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how)
1196 {
1197         int status = 0;
1198
1199         if (rp == NULL)
1200                 return 0;
1201         if (rp->output.fp == stdout || rp->output.fp == stderr)
1202                 goto checkwarn;         /* bypass closing, remove from list */
1203
1204         if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL)
1205                 lintwarn(_("close: redirection `%s' not opened with `|&', second argument ignored"),
1206                                 rp->value);
1207
1208         status = close_rp(rp, how);
1209
1210         if (status != 0) {
1211                 int save_errno = errno;
1212                 char *s = strerror(save_errno);
1213
1214                 /*
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.
1219                  */
1220                 if (do_lint) {
1221                         if ((rp->flag & RED_PIPE) != 0)
1222                                 lintwarn(_("failure status (%d) on pipe close of `%s' (%s)"),
1223                                          status, rp->value, s);
1224                         else
1225                                 lintwarn(_("failure status (%d) on file close of `%s' (%s)"),
1226                                          status, rp->value, s);
1227                 }
1228
1229                 if (! do_traditional) {
1230                         /* set ERRNO too so that program can get at it */
1231                         update_ERRNO_int(save_errno);
1232                 }
1233         }
1234
1235 checkwarn:
1236         if (exitwarn) {
1237                 /*
1238                  * Don't use lintwarn() here.  If lint warnings are fatal,
1239                  * doing so prevents us from closing other open redirections.
1240                  *
1241                  * Using multiple full messages instead of string parameters
1242                  * for the types makes message translation easier.
1243                  */
1244                 if ((rp->flag & RED_SOCKET) != 0)
1245                         warning(_("no explicit close of socket `%s' provided"),
1246                                 rp->value);
1247                 else if ((rp->flag & RED_TWOWAY) != 0)
1248                         warning(_("no explicit close of co-process `%s' provided"),
1249                                 rp->value);
1250                 else if ((rp->flag & RED_PIPE) != 0)
1251                         warning(_("no explicit close of pipe `%s' provided"),
1252                                 rp->value);
1253                 else
1254                         warning(_("no explicit close of file `%s' provided"),
1255                                 rp->value);
1256         }
1257
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;
1264                 else
1265                         red_head = rp->next;
1266                 free_rp(rp);
1267         }
1268
1269         return status;
1270 }
1271
1272 /* flush_io --- flush all open output files */
1273
1274 int
1275 flush_io()
1276 {
1277         struct redirect *rp;
1278         int status = 0;
1279
1280         errno = 0;
1281         /* we don't warn about stdout/stderr if EPIPE, but we do error exit */
1282         if (fflush(stdout)) {
1283                 if (errno != EPIPE)
1284                         warning(_("error writing standard output (%s)"), strerror(errno));
1285                 status++;
1286         }
1287         if (fflush(stderr)) {
1288                 if (errno != EPIPE)
1289                         warning(_("error writing standard error (%s)"), strerror(errno));
1290                 status++;
1291         }
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));
1302                                 else
1303                                         warning(_("file flush of `%s' failed (%s)."),
1304                                                 rp->value, strerror(errno));
1305                                 status++;
1306                         }
1307                 }
1308         if (status != 0)
1309                 status = -1;    /* canonicalize it */
1310         return status;
1311 }
1312
1313 /* close_io --- close all open files, called when exiting */
1314
1315 int
1316 close_io(bool *stdio_problem)
1317 {
1318         struct redirect *rp;
1319         struct redirect *next;
1320         int status = 0;
1321
1322         errno = 0;
1323         for (rp = red_head; rp != NULL; rp = next) {
1324                 next = rp->next;
1325                 /*
1326                  * close_redir() will print a message if needed.
1327                  * if do_lint, warn about lack of explicit close
1328                  */
1329                 if (close_redir(rp, do_lint, CLOSE_ALL))
1330                         status++;
1331                 rp = NULL;
1332         }
1333         /*
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.
1337          */
1338         *stdio_problem = false;
1339         /* we don't warn about stdout/stderr if EPIPE, but we do error exit */
1340         if (fflush(stdout) != 0) {
1341                 if (errno != EPIPE)
1342                         warning(_("error writing standard output (%s)"), strerror(errno));
1343                 status++;
1344                 *stdio_problem = true;
1345         }
1346         if (fflush(stderr) != 0) {
1347                 if (errno != EPIPE)
1348                         warning(_("error writing standard error (%s)"), strerror(errno));
1349                 status++;
1350                 *stdio_problem = true;
1351         }
1352         return status;
1353 }
1354
1355 /* str2mode --- convert a string mode to an integer mode */
1356
1357 static int
1358 str2mode(const char *mode)
1359 {
1360         int ret;
1361         const char *second = & mode[1];
1362
1363         if (*second == 'b')
1364                 second++;
1365
1366         switch(mode[0]) {
1367         case 'r':
1368                 ret = O_RDONLY;
1369                 if (*second == '+' || *second == 'w')
1370                         ret = O_RDWR;
1371                 break;
1372
1373         case 'w':
1374                 ret = O_WRONLY|O_CREAT|O_TRUNC;
1375                 if (*second == '+' || *second == 'r')
1376                         ret = O_RDWR|O_CREAT|O_TRUNC;
1377                 break;
1378
1379         case 'a':
1380                 ret = O_WRONLY|O_APPEND|O_CREAT;
1381                 if (*second == '+')
1382                         ret = O_RDWR|O_APPEND|O_CREAT;
1383                 break;
1384
1385         default:
1386                 ret = 0;                /* lint */
1387                 cant_happen();
1388         }
1389         if (strchr(mode, 'b') != NULL)
1390                 ret |= O_BINARY;
1391         return ret;
1392 }
1393
1394 #ifdef HAVE_SOCKETS
1395
1396 /* socketopen --- open a socket and set it into connected state */
1397
1398 static int
1399 socketopen(int family, int type, const char *localpname,
1400         const char *remotepname, const char *remotehostname)
1401 {
1402         struct addrinfo *lres, *lres0;
1403         struct addrinfo lhints;
1404         struct addrinfo *rres, *rres0;
1405         struct addrinfo rhints;
1406
1407         int lerror, rerror;
1408
1409         int socket_fd = INVALID_HANDLE;
1410         int any_remote_host = (strcmp(remotehostname, "0") == 0);
1411
1412         memset(& lhints, '\0', sizeof (lhints));
1413         lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
1414         lhints.ai_socktype = type;
1415         lhints.ai_family = family;
1416
1417         lerror = getaddrinfo(NULL, localpname, & lhints, & lres);
1418         if (lerror) {
1419                 if (strcmp(localpname, "0") != 0)
1420                         fatal(_("local port %s invalid in `/inet'"), localpname);
1421                 lres0 = NULL;
1422                 lres = & lhints;
1423         } else
1424                 lres0 = lres;
1425
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;
1432
1433                 rerror = getaddrinfo(any_remote_host ? NULL : remotehostname,
1434                                 remotepname, & rhints, & rres);
1435                 if (rerror) {
1436                         if (lres0 != NULL)
1437                                 freeaddrinfo(lres0);
1438                         fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname);
1439                 }
1440                 rres0 = rres;
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)
1446                                 goto nextrres;
1447
1448                         if (type == SOCK_STREAM) {
1449                                 int on = 1;
1450 #ifdef SO_LINGER
1451                                 struct linger linger;
1452                                 memset(& linger, '\0', sizeof(linger));
1453 #endif
1454                                 setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
1455                                         (char *) & on, sizeof(on));
1456 #ifdef SO_LINGER
1457                                 linger.l_onoff = 1;
1458                                 /* linger for 30/100 second */
1459                                 linger.l_linger = 30;
1460                                 setsockopt(socket_fd, SOL_SOCKET, SO_LINGER,
1461                                         (char *) & linger, sizeof(linger));
1462 #endif
1463                         }
1464                         if (bind(socket_fd, lres->ai_addr, lres->ai_addrlen) != 0)
1465                                 goto nextrres;
1466
1467                         if (! any_remote_host) { /* not ANY => create a client */
1468                                 if (connect(socket_fd, rres->ai_addr, rres->ai_addrlen) == 0)
1469                                         break;
1470                         } else { /* remote host is ANY => create a server */
1471                                 if (type == SOCK_STREAM) {
1472                                         int clientsocket_fd = INVALID_HANDLE;
1473
1474                                         struct sockaddr_storage remote_addr;
1475                                         socklen_t namelen = sizeof(remote_addr);
1476
1477                                         if (listen(socket_fd, 1) >= 0
1478                                             && (clientsocket_fd = accept(socket_fd,
1479                                                 (struct sockaddr *) & remote_addr,
1480                                                 & namelen)) >= 0) {
1481                                                 closemaybesocket(socket_fd);
1482                                                 socket_fd = clientsocket_fd;
1483                                                 break;
1484                                         }
1485                                 } else if (type == SOCK_DGRAM) {
1486 #ifdef MSG_PEEK
1487                                         char buf[10];
1488                                         struct sockaddr_storage remote_addr;
1489                                         socklen_t read_len = 0;
1490
1491                                         if (recvfrom(socket_fd, buf, 1, MSG_PEEK,
1492                                                 (struct sockaddr *) & remote_addr,
1493                                                         & read_len) >= 0
1494                                                         && read_len
1495                                                         && connect(socket_fd,
1496                                                 (struct sockaddr *) & remote_addr,
1497                                                                 read_len) == 0)
1498                                                         break;
1499 #endif
1500                                 }
1501                         }
1502
1503 nextrres:
1504                         if (socket_fd != INVALID_HANDLE)
1505                                 closemaybesocket(socket_fd);
1506                         socket_fd = INVALID_HANDLE;
1507                         rres = rres->ai_next;
1508                 }
1509                 freeaddrinfo(rres0);
1510                 if (socket_fd != INVALID_HANDLE)
1511                         break;
1512                 lres = lres->ai_next;
1513         }
1514         if (lres0)
1515                 freeaddrinfo(lres0);
1516
1517         return socket_fd;
1518 }
1519 #endif /* HAVE_SOCKETS */
1520
1521 /* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
1522
1523 /*
1524  * Strictly speaking, "name" is not a "const char *" because we temporarily
1525  * change the string.
1526  */
1527
1528 int
1529 devopen(const char *name, const char *mode)
1530 {
1531         int openfd;
1532         char *cp;
1533         char *ptr;
1534         int flag = 0;
1535         int len;
1536         int family;
1537
1538         if (strcmp(name, "-") == 0)
1539                 return fileno(stdin);
1540
1541         flag = str2mode(mode);
1542         openfd = INVALID_HANDLE;
1543
1544         if (do_traditional)
1545                 goto strictopen;
1546
1547         if ((openfd = os_devopen(name, flag)) != INVALID_HANDLE) {
1548                 os_close_on_exec(openfd, name, "file", "");
1549                 return openfd;
1550         }
1551
1552         if (strncmp(name, "/dev/", 5) == 0) {
1553                 cp = (char *) name + 5;
1554
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) {
1562                         struct stat sbuf;
1563
1564                         cp += 3;
1565                         openfd = (int) strtoul(cp, & ptr, 10);
1566                         if (openfd <= INVALID_HANDLE || ptr == cp
1567                             || fstat(openfd, & sbuf) < 0)
1568                                 openfd = INVALID_HANDLE;
1569                 }
1570                 /* do not set close-on-exec for inherited fd's */
1571                 if (openfd != INVALID_HANDLE)
1572                         return openfd;
1573         } else if (inetfile(name, & len, & family)) {
1574 #ifdef HAVE_SOCKETS
1575                 /* /inet/protocol/localport/hostname/remoteport */
1576                 int protocol;
1577                 char *hostname;
1578                 char *hostnameslastcharp;
1579                 char *localpname;
1580                 char *localpnamelastcharp;
1581
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;
1588                 else {
1589                         protocol = SOCK_STREAM; /* shut up the compiler */
1590                         fatal(_("no (known) protocol supplied in special filename `%s'"),
1591                                                 name);
1592                 }
1593                 cp += 4;
1594
1595                 /* which localport? */
1596                 localpname = cp;
1597                 while (*cp != '/' && *cp != '\0')
1598                         cp++;
1599                 /*                    
1600                  * Require a port, let them explicitly put 0 if
1601                  * they don't care.  
1602                  */
1603                 if (*cp != '/' || cp == localpname)
1604                         fatal(_("special file name `%s' is incomplete"), name);
1605
1606                 /*
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.
1610                  */
1611                 *cp = '\0';
1612                 localpnamelastcharp = cp;
1613
1614                 /* which hostname? */
1615                 cp++;
1616                 hostname = cp;
1617                 while (*cp != '/' && *cp != '\0')
1618                         cp++; 
1619                 if (*cp != '/' || cp == hostname) {
1620                         *localpnamelastcharp = '/';
1621                         fatal(_("must supply a remote hostname to `/inet'"));
1622                 }
1623                 *cp = '\0';
1624                 hostnameslastcharp = cp;
1625
1626                 /* which remoteport? */
1627                 cp++;
1628                 /*
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.
1632                  *
1633                  * Here too, require a port, let them explicitly put 0 if
1634                  * they don't care.
1635                  */
1636                 if (*cp == '\0') {
1637                         *localpnamelastcharp = '/';
1638                         *hostnameslastcharp = '/';
1639                         fatal(_("must supply a remote port to `/inet'"));
1640                 }
1641
1642                 {
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;
1648
1649                 if (first_time) {
1650                         char *cp, *end;
1651                         unsigned long count = 0;
1652                         char *ms2;
1653                         
1654                         first_time = false;
1655                         if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) {
1656                                 count = strtoul(cp, & end, 10);
1657                                 if (end != cp && count > 0)
1658                                         def_retries = count;
1659                         }
1660
1661                         /*
1662                          * Env var is in milliseconds, paramter to usleep()
1663                          * is microseconds, make the conversion. Default is
1664                          * 1 millisecond.
1665                          */
1666                         if ((ms2 = getenv("GAWK_MSEC_SLEEP")) != NULL) {
1667                                 msleep = strtol(ms2, & end, 10);
1668                                 if (end == ms2 || msleep < 0)
1669                                         msleep = 1000;
1670                                 else
1671                                         msleep *= 1000;
1672                         }
1673                 }
1674                 retries = def_retries;
1675
1676                 do {
1677                         openfd = socketopen(family, protocol, localpname, cp, hostname);
1678                         retries--;
1679                 } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0);
1680         }
1681
1682         *localpnamelastcharp = '/';
1683         *hostnameslastcharp = '/';
1684 #else /* ! HAVE_SOCKETS */
1685         fatal(_("TCP/IP communications are not supported"));
1686 #endif /* HAVE_SOCKETS */
1687         }
1688
1689 strictopen:
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
1695                    not permitted.  */
1696                 struct stat buf;
1697                 int l, f;
1698
1699                 if (!inetfile(name, &l, &f)
1700                     && stat(name, & buf) == 0 && S_ISDIR(buf.st_mode))
1701                         errno = EISDIR;
1702         }
1703 #endif
1704         if (openfd != INVALID_HANDLE) {
1705                 if (openfd > fileno(stderr))
1706                         os_close_on_exec(openfd, name, "file", "");
1707         }
1708
1709         return openfd;
1710 }
1711
1712 /* two_way_open --- open a two way communications channel */
1713
1714 static int
1715 two_way_open(const char *str, struct redirect *rp)
1716 {
1717         static bool no_ptys = false;
1718
1719 #ifdef HAVE_SOCKETS
1720         /* case 1: socket */
1721         if (inetfile(str, NULL, NULL)) {
1722                 int fd, newfd;
1723
1724                 fd = devopen(str, "rw");
1725                 if (fd == INVALID_HANDLE)
1726                         return false;
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) {
1731                         close(fd);
1732                         return false;
1733                 }
1734                 newfd = dup(fd);
1735                 if (newfd < 0) {
1736                         rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1737                         return false;
1738                 }
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);
1750                         iop_close(rp->iop);
1751                         rp->iop = NULL;
1752                         rp->output.gawk_fclose(rp->output.fp, rp->output.opaque);
1753                         return false;
1754                 }
1755                 rp->flag |= RED_SOCKET;
1756                 return true;
1757         }
1758 #endif /* HAVE_SOCKETS */
1759
1760         /* case 2: see if an extension wants it */
1761         if (find_two_way_processor(str, rp))
1762                 return true;
1763
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;
1771 #endif
1772                 char slavenam[32];
1773                 char c;
1774                 int master, dup_master;
1775                 int slave;
1776                 int save_errno; 
1777                 pid_t pid;
1778                 struct stat statb;
1779                 struct termios st;
1780                 /* Use array of chars to avoid ASCII / EBCDIC issues */
1781                 static char pty_chars[] = "pqrstuvwxyzabcdefghijklmno";
1782                 int i;
1783
1784                 if (! initialized) {
1785                         initialized = true;
1786 #if defined(HAVE_GRANTPT) && ! defined(HAVE_POSIX_OPENPT)
1787                         have_dev_ptmx = (stat("/dev/ptmx", & statb) >= 0);
1788 #endif
1789                         i = 0;
1790                         do {
1791                                 c = pty_chars[i++];
1792                                 sprintf(slavenam, "/dev/pty%c0", c);
1793                                 if (stat(slavenam, & statb) >= 0) {
1794                                         first_pty_letter = c;
1795                                         break;
1796                                 }
1797                         } while (pty_chars[i] != '\0');
1798                 }
1799
1800 #ifdef HAVE_GRANTPT
1801 #ifdef HAVE_POSIX_OPENPT
1802                 {
1803                         master = posix_openpt(O_RDWR|O_NOCTTY);
1804 #else
1805                 if (have_dev_ptmx) {
1806                         master = open("/dev/ptmx", O_RDWR);
1807 #endif
1808                         if (master >= 0) {
1809                                 char *tem;
1810
1811                                 grantpt(master);
1812                                 unlockpt(master);
1813                                 tem = ptsname(master);
1814                                 if (tem != NULL) {
1815                                         strcpy(slavenam, tem);
1816                                         goto got_the_pty;
1817                                 }
1818                                 (void) close(master);
1819                         }
1820                 }
1821 #endif
1822
1823                 if (first_pty_letter) {
1824                         /*
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?
1830                          */
1831                         c = first_pty_letter;
1832                         do {
1833                                 int i;
1834                                 char *cp;
1835
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 */
1840                                                 goto use_pipes;
1841                                         }
1842
1843                                         if ((master = open(slavenam, O_RDWR)) >= 0) {
1844                                                 slavenam[sizeof("/dev/") - 1] = 't';
1845                                                 if (access(slavenam, R_OK | W_OK) == 0)
1846                                                         goto got_the_pty;
1847                                                 close(master);
1848                                         }
1849                                 }
1850                                 /* move to next character */
1851                                 cp = strchr(pty_chars, c);
1852                                 if (cp[1] != '\0')
1853                                         cp++;
1854                                 else
1855                                         cp = pty_chars;
1856                                 c = *cp;
1857                         } while (c != first_pty_letter);
1858                 } else
1859                         no_ptys = true;
1860
1861                 /* Couldn't find a pty. Fall back to using pipes. */
1862                 goto use_pipes;
1863
1864         got_the_pty:
1865                 if ((slave = open(slavenam, O_RDWR)) < 0) {
1866                         close(master);
1867                         fatal(_("could not open `%s', mode `%s'"),
1868                                 slavenam, "r+");
1869                 }
1870
1871 #ifdef I_PUSH
1872                 /*
1873                  * Push the necessary modules onto the slave to
1874                  * get terminal semantics.
1875                  */
1876                 ioctl(slave, I_PUSH, "ptem");
1877                 ioctl(slave, I_PUSH, "ldterm");
1878 #endif
1879
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);
1887                 st.c_lflag |= ISIG;
1888
1889                 /* Set some control codes to default values */
1890 #ifdef VINTR
1891                 st.c_cc[VINTR] = '\003';        /* ^c */
1892 #endif
1893 #ifdef VQUIT
1894                 st.c_cc[VQUIT] = '\034';        /* ^| */
1895 #endif
1896 #ifdef VERASE
1897                 st.c_cc[VERASE] = '\177';       /* ^? */
1898 #endif
1899 #ifdef VKILL
1900                 st.c_cc[VKILL] = '\025';        /* ^u */
1901 #endif
1902 #ifdef VEOF
1903                 st.c_cc[VEOF] = '\004'; /* ^d */
1904 #endif
1905                 tcsetattr(slave, TCSANOW, & st);
1906
1907                 switch (pid = fork()) {
1908                 case 0:
1909                         /* Child process */
1910                         setsid();
1911
1912 #ifdef TIOCSCTTY
1913                         ioctl(slave, TIOCSCTTY, 0);
1914 #endif
1915
1916                         if (close(master) == -1)
1917                                 fatal(_("close of master pty failed (%s)"), strerror(errno));
1918                         if (close(1) == -1)
1919                                 fatal(_("close of stdout in child failed (%s)"),
1920                                         strerror(errno));
1921                         if (dup(slave) != 1)
1922                                 fatal(_("moving slave pty to stdout in child failed (dup: %s)"), strerror(errno));
1923                         if (close(0) == -1)
1924                                 fatal(_("close of stdin in child failed (%s)"),
1925                                         strerror(errno));
1926                         if (dup(slave) != 0)
1927                                 fatal(_("moving slave pty to stdin in child failed (dup: %s)"), strerror(errno));
1928                         if (close(slave))
1929                                 fatal(_("close of slave pty failed (%s)"), strerror(errno));
1930
1931                         /* stderr does NOT get dup'ed onto child's stdout */
1932
1933                         signal(SIGPIPE, SIG_DFL);
1934
1935                         execl("/bin/sh", "sh", "-c", str, NULL);
1936                         _exit(errno == ENOENT ? 127 : 126);
1937
1938                 case -1:
1939                         save_errno = errno;
1940                         close(master);
1941                         close(slave);
1942                         errno = save_errno;
1943                         return false;
1944
1945                 }
1946
1947                 /* parent */
1948                 if (close(slave) != 0) {
1949                         close(master);
1950                         (void) kill(pid, SIGKILL);
1951                         fatal(_("close of slave pty failed (%s)"), strerror(errno));
1952                 }
1953
1954                 rp->pid = pid;
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);
1961                         iop_close(rp->iop);
1962                         rp->iop = NULL;
1963                         (void) kill(pid, SIGKILL);
1964                         return false;
1965                 }
1966
1967                 rp->output.name = str;
1968                 /*
1969                  * Force read and write ends of two-way connection to
1970                  * be different fd's so they can be closed independently.
1971                  */
1972                 rp->output.mode = "w";
1973                 if ((dup_master = dup(master)) < 0
1974                     || (rp->output.fp = fdopen(dup_master, "w")) == NULL) {
1975                         iop_close(rp->iop);
1976                         rp->iop = NULL;
1977                         (void) close(master);
1978                         (void) kill(pid, SIGKILL);
1979                         if (dup_master > 0)
1980                                 (void) close(dup_master);
1981                         return false;
1982                 } else
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 */
1988                 return true;
1989         }
1990 #endif /* defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS) */
1991
1992 use_pipes:
1993 #ifndef PIPES_SIMULATED         /* real pipes */
1994         /* case 4: two way pipe to a child process */
1995     {
1996         int ptoc[2], ctop[2];
1997         int pid;
1998         int save_errno;
1999 #if defined(__EMX__) || defined(__MINGW32__)
2000         int save_stdout, save_stdin;
2001 #ifdef __MINGW32__
2002         char *qcmd = NULL;
2003 #endif
2004 #endif
2005
2006         if (pipe(ptoc) < 0)
2007                 return false;   /* errno set, diagnostic from caller */
2008
2009         if (pipe(ctop) < 0) {
2010                 save_errno = errno;
2011                 close(ptoc[0]);
2012                 close(ptoc[1]);
2013                 errno = save_errno;
2014                 return false;
2015         }
2016
2017 #if defined(__EMX__) || defined(__MINGW32__)
2018         save_stdin = dup(0);    /* duplicate stdin */
2019         save_stdout = dup(1);   /* duplicate stdout */
2020         
2021         if (save_stdout == -1 || save_stdin == -1) {
2022                 /* if an error occurs close all open file handles */
2023                 save_errno = errno;
2024                 if (save_stdin != -1)
2025                         close(save_stdin);
2026                 if (save_stdout != -1)
2027                         close(save_stdout);
2028                 close(ptoc[0]); close(ptoc[1]);
2029                 close(ctop[0]); close(ctop[1]);
2030                 errno = save_errno;
2031                 return false;
2032         }
2033         
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));
2041         }
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));
2048         }
2049
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 */
2053         
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 */
2058
2059         /* stderr does NOT get dup'ed onto child's stdout */
2060 #ifdef __EMX__
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);
2065         efree(qcmd);
2066 #endif
2067         
2068         /* restore stdin and stdout */
2069         close(1);
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"));
2074         }
2075         close(save_stdout);
2076         
2077         close(0);
2078         if (dup(save_stdin) != 0) {
2079                 close(save_stdin);
2080                 close(ptoc[1]); close(ctop[0]);
2081                 fatal(_("restoring stdin in parent process failed\n"));
2082         }
2083         close(save_stdin);
2084
2085         if (pid < 0) { /* spawnl() failed */
2086                 save_errno = errno;
2087                 close(ptoc[1]);
2088                 close(ctop[0]);
2089
2090                 errno = save_errno;
2091                 return false;
2092         }
2093
2094 #else /* NOT __EMX__, NOT __MINGW32__ */
2095         if ((pid = fork()) < 0) {
2096                 save_errno = errno;
2097                 close(ptoc[0]); close(ptoc[1]);
2098                 close(ctop[0]); close(ctop[1]);
2099                 errno = save_errno;
2100                 return false;
2101         }
2102         
2103         if (pid == 0) { /* child */
2104                 if (close(1) == -1)
2105                         fatal(_("close of stdout in child failed (%s)"),
2106                                 strerror(errno));
2107                 if (dup(ctop[1]) != 1)
2108                         fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno));
2109                 if (close(0) == -1)
2110                         fatal(_("close of stdin in child failed (%s)"),
2111                                 strerror(errno));
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);
2120         }
2121 #endif /* NOT __EMX__, NOT __MINGW32__ */
2122
2123         /* parent */
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);
2128         rp->pid = pid;
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);
2135                 iop_close(rp->iop);
2136                 rp->iop = NULL;
2137                 (void) close(ctop[1]);
2138                 (void) close(ptoc[0]);
2139                 (void) close(ptoc[1]);
2140                 (void) kill(pid, SIGKILL);
2141
2142                 return false;
2143         }
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) {
2148                 iop_close(rp->iop);
2149                 rp->iop = 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);
2155
2156                 return false;
2157         }
2158         else
2159                 find_output_wrapper(& rp->output);
2160
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");
2164
2165         (void) close(ptoc[0]);
2166         (void) close(ctop[1]);
2167 #endif
2168
2169         return true;
2170     }
2171
2172 #else   /*PIPES_SIMULATED*/
2173
2174         fatal(_("`|&' not supported"));
2175         /*NOTREACHED*/
2176         return false;
2177
2178 #endif
2179 }
2180
2181 #ifndef PIPES_SIMULATED         /* real pipes */
2182
2183 /* wait_any --- wait for a child process, close associated pipe */
2184
2185 static int
2186 wait_any(int interesting)       /* pid of interest, if any */
2187 {
2188         RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int);
2189         int pid;
2190         int status = 0;
2191         struct redirect *redp;
2192
2193         istat = signal(SIGINT, SIG_IGN);
2194 #ifdef __MINGW32__
2195         if (interesting < 0) {
2196                 status = -1;
2197                 pid = -1;
2198         }
2199         else
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) {
2204                                 redp->pid = -1;
2205                                 redp->status = status;
2206                                 break;
2207                         }
2208         }
2209 #else
2210         hstat = signal(SIGHUP, SIG_IGN);
2211         qstat = signal(SIGQUIT, SIG_IGN);
2212         for (;;) {
2213 # ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */
2214                 pid = wait(& status);
2215 # else
2216                 pid = wait((union wait *) & status);
2217 # endif
2218                 if (interesting && pid == interesting) {
2219                         break;
2220                 } else if (pid != -1) {
2221                         for (redp = red_head; redp != NULL; redp = redp->next)
2222                                 if (pid == redp->pid) {
2223                                         redp->pid = -1;
2224                                         redp->status = status;
2225                                         break;
2226                                 }
2227                 }
2228                 if (pid == -1 && errno == ECHILD)
2229                         break;
2230         }
2231         signal(SIGHUP, hstat);
2232         signal(SIGQUIT, qstat);
2233 #endif
2234         signal(SIGINT, istat);
2235         return status;
2236 }
2237
2238 /* gawk_popen --- open an IOBUF on a child process */
2239
2240 static IOBUF *
2241 gawk_popen(const char *cmd, struct redirect *rp)
2242 {
2243         int p[2];
2244         int pid;
2245 #if defined(__EMX__) || defined(__MINGW32__)
2246         int save_stdout;
2247 #ifdef __MINGW32__
2248         char *qcmd = NULL;
2249 #endif
2250 #endif
2251
2252         /*
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).
2256          *
2257          * (void) wait_any(0);  // wait for outstanding processes
2258          */
2259
2260         if (pipe(p) < 0)
2261                 fatal(_("cannot open pipe `%s' (%s)"), cmd, strerror(errno));
2262
2263 #if defined(__EMX__) || defined(__MINGW32__)
2264         rp->iop = NULL;
2265         save_stdout = dup(1); /* save stdout */
2266         if (save_stdout == -1) {
2267                 close(p[0]);
2268                 close(p[1]);
2269                 return NULL;    /* failed */
2270         }
2271
2272         close(1); /* close stdout */
2273         if (dup(p[1]) != 1) {
2274                 close(p[0]);
2275                 close(p[1]);
2276                 fatal(_("moving pipe to stdout in child failed (dup: %s)"),
2277                                 strerror(errno));
2278         }
2279         
2280         /* none of these handles must be inherited by the child process */
2281         close(p[1]); /* close pipe input */
2282         
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 */
2285
2286 #ifdef __EMX__
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);
2291         efree(qcmd);
2292 #endif
2293         
2294         /* restore stdout */
2295         close(1);
2296         if (dup(save_stdout) != 1) {
2297                 close(p[0]);
2298                 fatal(_("restoring stdout in parent process failed\n"));
2299         }
2300         close(save_stdout);
2301
2302 #else /* NOT __EMX__, NOT __MINGW32__ */
2303         if ((pid = fork()) == 0) {
2304                 if (close(1) == -1)
2305                         fatal(_("close of stdout in child failed (%s)"),
2306                                 strerror(errno));
2307                 if (dup(p[1]) != 1)
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);
2313         }
2314 #endif /* NOT __EMX__, NOT __MINGW32__ */
2315
2316         if (pid == -1) {
2317                 close(p[0]); close(p[1]);
2318                 fatal(_("cannot create child process for `%s' (fork: %s)"), cmd, strerror(errno));
2319         }
2320         rp->pid = pid;
2321 #if !defined(__EMX__) && !defined(__MINGW32__)
2322         if (close(p[1]) == -1) {
2323                 close(p[0]);
2324                 fatal(_("close of pipe failed (%s)"), strerror(errno));
2325         }
2326 #endif
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);
2336                 iop_close(rp->iop);
2337                 rp->iop = NULL;
2338         }
2339
2340         return rp->iop;
2341 }
2342
2343 /* gawk_pclose --- close an open child pipe */
2344
2345 static int
2346 gawk_pclose(struct redirect *rp)
2347 {
2348         if (rp->iop != NULL)
2349                 (void) iop_close(rp->iop);
2350         rp->iop = NULL;
2351
2352         /* process previously found, return stored status */
2353         if (rp->pid == -1)
2354                 return rp->status;
2355         rp->status = wait_any(rp->pid);
2356         rp->pid = -1;
2357         return rp->status;
2358 }
2359
2360 #else   /* PIPES_SIMULATED */
2361
2362 /*
2363  * use temporary file rather than pipe
2364  * except if popen() provides real pipes too
2365  */
2366
2367 /* gawk_popen --- open an IOBUF on a child process */
2368
2369 static IOBUF *
2370 gawk_popen(const char *cmd, struct redirect *rp)
2371 {
2372         FILE *current;
2373
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)
2379                 return 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;
2389                 iop_close(rp->iop);
2390                 rp->iop = NULL;
2391                 current = NULL;
2392         }
2393         rp->ifp = current;
2394         return rp->iop;
2395 }
2396
2397 /* gawk_pclose --- close an open child pipe */
2398
2399 static int
2400 gawk_pclose(struct redirect *rp)
2401 {
2402         int rval, aval, fd = rp->iop->public.fd;
2403
2404         if (rp->iop != NULL) {
2405                 rp->iop->public.fd = dup(fd);     /* kludge to allow close() + pclose() */
2406                 rval = iop_close(rp->iop);
2407         }
2408         rp->iop = NULL;
2409         aval = pclose(rp->ifp);
2410         rp->ifp = NULL;
2411         return (rval < 0 ? rval : aval);
2412 }
2413
2414 #endif  /* PIPES_SIMULATED */
2415
2416 /* do_getline_redir --- read in a line, into var and with redirection */
2417
2418 NODE *
2419 do_getline_redir(int into_variable, enum redirval redirtype)
2420 {
2421         struct redirect *rp = NULL;
2422         IOBUF *iop;
2423         int cnt = EOF;
2424         char *s = NULL;
2425         int errcode;
2426         NODE *redir_exp = NULL;
2427         NODE **lhs = NULL;
2428         int redir_error = 0;
2429
2430         if (into_variable)
2431                 lhs = POP_ADDRESS();
2432
2433         assert(redirtype != redirect_none);
2434         redir_exp = TOP();
2435         rp = redirect(redir_exp, redirtype, & redir_error);
2436         DEREF(redir_exp);
2437         decr_sp();
2438         if (rp == NULL) {
2439                 if (redir_error) { /* failed redirect */
2440                         if (! do_traditional)
2441                                 update_ERRNO_int(redir_error);
2442                 }
2443                 return make_number((AWKNUM) -1.0);
2444         }
2445         iop = rp->iop;
2446         if (iop == NULL)                /* end of input */
2447                 return make_number((AWKNUM) 0.0);
2448
2449         errcode = 0;
2450         cnt = get_a_record(& s, iop, & errcode);
2451         if (errcode != 0) {
2452                 if (! do_traditional && (errcode != -1))
2453                         update_ERRNO_int(errcode);
2454                 return make_number((AWKNUM) -1.0);
2455         }
2456
2457         if (cnt == EOF) {
2458                 /*
2459                  * Don't do iop_close() here if we are
2460                  * reading from a pipe; otherwise
2461                  * gawk_pclose will not be called.
2462                  */
2463                 if ((rp->flag & (RED_PIPE|RED_TWOWAY)) == 0) {
2464                         (void) iop_close(iop);
2465                         rp->iop = NULL;
2466                 }
2467                 rp->flag |= RED_EOF;    /* sticky EOF */
2468                 return make_number((AWKNUM) 0.0);
2469         }
2470
2471         if (lhs == NULL)        /* no optional var. */
2472                 set_record(s, cnt);
2473         else {                  /* assignment to variable */
2474                 unref(*lhs);
2475                 *lhs = make_string(s, cnt);
2476                 (*lhs)->flags |= MAYBE_NUM;
2477         }
2478
2479         return make_number((AWKNUM) 1.0);
2480 }
2481
2482 /* do_getline --- read in a line, into var and without redirection */
2483
2484 NODE *
2485 do_getline(int into_variable, IOBUF *iop)
2486 {
2487         int cnt = EOF;
2488         char *s = NULL;
2489         int errcode;
2490
2491         if (iop == NULL) {      /* end of input */
2492                 if (into_variable)
2493                         (void) POP_ADDRESS();
2494                 return make_number((AWKNUM) 0.0);
2495         }
2496
2497         errcode = 0;
2498         cnt = get_a_record(& s, iop, & errcode);
2499         if (errcode != 0) {
2500                 if (! do_traditional && (errcode != -1))
2501                         update_ERRNO_int(errcode);
2502                 if (into_variable)
2503                         (void) POP_ADDRESS();
2504                 return make_number((AWKNUM) -1.0); 
2505         }
2506
2507         if (cnt == EOF)
2508                 return NULL;    /* try next file */
2509         INCREMENT_REC(NR);
2510         INCREMENT_REC(FNR);
2511
2512         if (! into_variable)    /* no optional var. */
2513                 set_record(s, cnt);
2514         else {                  /* assignment to variable */
2515                 NODE **lhs;
2516                 lhs = POP_ADDRESS();
2517                 unref(*lhs);
2518                 *lhs = make_string(s, cnt);
2519                 (*lhs)->flags |= MAYBE_NUM;
2520         }
2521         return make_number((AWKNUM) 1.0);
2522 }
2523
2524 typedef struct {
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 */ 
2530 } path_info;
2531
2532 static path_info pi_awkpath = {
2533         /* envname */   "AWKPATH",
2534         /* dfltp */     & defpath,
2535         /* try_cwd */   true,
2536 };
2537
2538 static path_info pi_awklibpath = {
2539         /* envname */   "AWKLIBPATH",
2540         /* dfltp */     & deflibpath,
2541         /* try_cwd */   false,
2542 };
2543
2544 /* init_awkpath --- split path(=$AWKPATH) into components */
2545
2546 static void
2547 init_awkpath(path_info *pi)
2548 {
2549         char *path;
2550         char *start, *end, *p;
2551         int len, i;
2552         int max_path;           /* (# of allocated paths)-1 */
2553
2554 #define INC_PATH 5
2555
2556         pi->max_pathlen = 0;
2557         if ((path = getenv(pi->envname)) == NULL || *path == '\0')
2558                 path = pi->dfltp[0];
2559
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 *));
2563
2564         end = start = path;
2565         i = 0;
2566         while (*start) {
2567                 while (*end && *end != envsep)
2568                         end++;
2569                 len = end - start;
2570                 if (len > 0) {
2571                         emalloc(p, char *, len + 2, "init_awkpath");
2572                         memcpy(p, start, len);
2573
2574                         /* add directory punctuation if necessary */
2575                         if (! isdirpunct(end[-1]))
2576                                 p[len++] = '/';
2577                         p[len] = '\0';
2578
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 *));
2583                         }
2584                         pi->awkpath[i++] = p;
2585                         if (len > pi->max_pathlen)
2586                                 pi->max_pathlen = len;
2587                 }
2588
2589                 /* skip one or more envsep char */
2590                 while (*end && *end == envsep)
2591                         end++;
2592                 start = end;
2593         }
2594         pi->awkpath[i] = NULL;
2595
2596 #undef INC_PATH
2597 }
2598
2599 /* get_cwd -- get current working directory */
2600
2601 static char *
2602 get_cwd ()
2603 {
2604 #define BSIZE   100
2605         char *buf;
2606         size_t bsize = BSIZE;
2607
2608         emalloc(buf, char *, bsize * sizeof(char), "get_cwd");
2609         while (true) {
2610                 if (getcwd(buf, bsize) == buf)
2611                         return buf;
2612                 if (errno != ERANGE) {
2613                         efree(buf);
2614                         return NULL;
2615                 }
2616                 bsize *= 2;
2617                 erealloc(buf, char *, bsize * sizeof(char), "get_cwd");
2618         }
2619 #undef BSIZE
2620 }
2621
2622
2623 /* do_find_source --- search $AWKPATH for file, return NULL if not found */ 
2624
2625 static char *
2626 do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi)
2627 {
2628         char *path;
2629         int i;
2630
2631         assert(errcode != NULL);
2632
2633         /* some kind of path name, no search */
2634         if (ispath(src)) {
2635                 emalloc(path, char *, strlen(src) + 1, "do_find_source");
2636                 strcpy(path, src);
2637                 if (stat(path, stb) == 0)
2638                         return path;
2639                 *errcode = errno;
2640                 efree(path);
2641                 return NULL;
2642         }
2643
2644         /* try current directory before $AWKPATH search */
2645         if (pi->try_cwd && stat(src, stb) == 0) {
2646                 path = get_cwd();
2647                 if (path == NULL) {
2648                         *errcode = errno;
2649                         return NULL;
2650                 }
2651                 erealloc(path, char *, strlen(path) + strlen(src) + 2, "do_find_source");
2652 #ifdef VMS
2653                 if (strcspn(path,">]:") == strlen(path))
2654                         strcat(path, "/");
2655 #else
2656                 strcat(path, "/");
2657 #endif
2658                 strcat(path, src);
2659                 return path;
2660         }
2661
2662         if (pi->awkpath == NULL)
2663                 init_awkpath(pi);
2664
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)
2668                         *path = '\0';
2669                 else
2670                         strcpy(path, pi->awkpath[i]);
2671                 strcat(path, src);
2672                 if (stat(path, stb) == 0)
2673                         return path;
2674         }
2675
2676         /* not found, give up */
2677         *errcode = errno;
2678         efree(path);
2679         return NULL;
2680 }
2681
2682 /* find_source --- find source file with default file extension handling */ 
2683
2684 char *
2685 find_source(const char *src, struct stat *stb, int *errcode, int is_extlib)
2686 {
2687         char *path;
2688         path_info *pi = (is_extlib ? & pi_awklibpath : & pi_awkpath);
2689
2690         *errcode = 0;
2691         if (src == NULL || *src == '\0')
2692                 return NULL;
2693         path = do_find_source(src, stb, errcode, pi);
2694
2695         if (path == NULL && is_extlib) {
2696                 char *file_ext;
2697                 int save_errno;
2698                 size_t src_len;
2699                 size_t suffix_len;
2700
2701 #define EXTLIB_SUFFIX   "." SHLIBEXT
2702                 src_len = strlen(src);
2703                 suffix_len = strlen(EXTLIB_SUFFIX);
2704
2705                 /* check if already has the SUFFIX */
2706                 if (src_len >= suffix_len && strcmp(& src[src_len - suffix_len], EXTLIB_SUFFIX) == 0)
2707                         return NULL;
2708
2709                 /* append EXTLIB_SUFFIX and try again */
2710                 save_errno = errno;
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);
2714                 efree(file_ext);
2715                 if (path == NULL)
2716                         errno = save_errno;
2717                 return path;
2718 #undef EXTLIB_SUFFIX
2719         }
2720
2721 /*
2722  * Try searching with .awk appended if the platform headers have not specified
2723  * another suffix.
2724  */
2725 #ifndef DEFAULT_FILETYPE
2726 #define DEFAULT_FILETYPE ".awk"
2727 #endif
2728
2729 #ifdef DEFAULT_FILETYPE
2730         if (! do_traditional && path == NULL) {
2731                 char *file_awk;
2732                 int save_errno = errno;
2733 #ifdef VMS
2734                 int vms_save = vaxc$errno;
2735 #endif
2736
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);
2742                 efree(file_awk);
2743                 if (path == NULL) {
2744                         errno = save_errno;
2745 #ifdef VMS
2746                         vaxc$errno = vms_save;
2747 #endif
2748                 }
2749         }
2750 #endif  /*DEFAULT_FILETYPE*/
2751
2752         return path;
2753 }
2754
2755
2756 /* srcopen --- open source file */
2757
2758 int
2759 srcopen(SRCFILE *s)
2760 {
2761         int fd = INVALID_HANDLE;
2762
2763         if (s->stype == SRC_STDIN)
2764                 fd = fileno(stdin);
2765         else if (s->stype == SRC_FILE || s->stype == SRC_INC)
2766                 fd = devopen(s->fullpath, "r");
2767
2768         /* set binary mode so that debugger byte offset calculations will be right */
2769         if (fd != INVALID_HANDLE)
2770                 os_setbinmode(fd, O_BINARY);
2771
2772         return fd;
2773 }
2774
2775 /* input parsers, mainly for use by extension functions */
2776
2777 static awk_input_parser_t *ip_head, *ip_tail;
2778
2779 /*
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.
2784  */
2785
2786 void
2787 register_input_parser(awk_input_parser_t *input_parser)
2788 {
2789         if (input_parser == NULL)
2790                 fatal(_("register_input_parser: received NULL pointer"));
2791
2792         input_parser->next = NULL;      /* force it */
2793         if (ip_head == NULL) {
2794                 ip_head = ip_tail = input_parser;
2795         } else {
2796                 ip_tail->next = input_parser;
2797                 ip_tail = ip_tail->next;
2798         }
2799 }
2800
2801 /* find_input_parser --- search the list of input parsers */
2802
2803 static void
2804 find_input_parser(IOBUF *iop)
2805 {
2806         awk_input_parser_t *ip, *ip2;
2807
2808         /* if already associated with an input parser, bail out early */
2809         if (iop->public.get_record != NULL)
2810                 return;
2811
2812         ip = ip2 = NULL;
2813         for (ip2 = ip_head; ip2 != NULL; ip2 = ip2->next) {
2814                 if (ip2->can_take_file(& iop->public)) {
2815                         if (ip == NULL)
2816                                 ip = ip2;       /* found first one */
2817                         else
2818                                 fatal(_("input parser `%s' conflicts with previously installed input parser `%s'"),
2819                                                 ip2->name, ip->name);
2820                 }
2821         }
2822
2823         if (ip != NULL) {
2824                 if (! ip->take_control_of(& iop->public))
2825                         warning(_("input parser `%s' failed to open `%s'"),
2826                                         ip->name, iop->public.name);
2827                 else
2828                         iop->valid = true;
2829         }
2830 }
2831
2832 /* output wrappers --- for use by extensions */
2833
2834 static awk_output_wrapper_t *op_head, *op_tail;
2835
2836 /*
2837  * register_output_wrapper --- add an output wrapper to the list.
2838  *      Same stuff here as for input parsers.
2839  */
2840
2841 void
2842 register_output_wrapper(awk_output_wrapper_t *wrapper)
2843 {
2844         if (wrapper == NULL)
2845                 fatal(_("register_output_wrapper: received NULL pointer"));
2846
2847         wrapper->next = NULL;   /* force it */
2848         if (op_head == NULL) {
2849                 op_head = op_tail = wrapper;
2850         } else {
2851                 op_tail->next = wrapper;
2852                 op_tail = op_tail->next;
2853         }
2854 }
2855
2856 /* find_output_wrapper --- search the list of output wrappers */
2857
2858 static bool
2859 find_output_wrapper(awk_output_buf_t *outbuf)
2860 {
2861         awk_output_wrapper_t *op, *op2;
2862
2863         /* if already associated with an output wrapper, bail out early */
2864         if (outbuf->redirected)
2865                 return false;
2866
2867         op = op2 = NULL;
2868         for (op2 = op_head; op2 != NULL; op2 = op2->next) {
2869                 if (op2->can_take_file(outbuf)) {
2870                         if (op == NULL)
2871                                 op = op2;       /* found first one */
2872                         else
2873                                 fatal(_("output wrapper `%s' conflicts with previously installed output wrapper `%s'"),
2874                                                 op2->name, op->name);
2875                 }
2876         }
2877
2878         if (op != NULL) {
2879                 if (! op->take_control_of(outbuf)) {
2880                         warning(_("output wrapper `%s' failed to open `%s'"),
2881                                         op->name, outbuf->name);
2882                         return false;
2883                 }
2884                 return true;
2885         }
2886
2887         return false;
2888 }
2889
2890
2891 /* two way processors --- for use by extensions */
2892
2893 static awk_two_way_processor_t *tw_head, *tw_tail;
2894
2895 /* register_two_way_processor --- register a two-way I/O processor, for extensions */
2896
2897 void
2898 register_two_way_processor(awk_two_way_processor_t *processor)
2899 {
2900         if (processor == NULL)
2901                 fatal(_("register_output_processor: received NULL pointer"));
2902
2903         processor->next = NULL; /* force it */
2904         if (tw_head == NULL) {
2905                 tw_head = tw_tail = processor;
2906         } else {
2907                 tw_tail->next = processor;
2908                 tw_tail = tw_tail->next;
2909         }
2910 }
2911
2912 /* find_two_way_processor --- search the list of two way processors */
2913
2914 static bool
2915 find_two_way_processor(const char *name, struct redirect *rp)
2916 {
2917         awk_two_way_processor_t *tw, *tw2;
2918
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)
2922                 return false;
2923
2924         tw = tw2 = NULL;
2925         for (tw2 = tw_head; tw2 != NULL; tw2 = tw2->next) {
2926                 if (tw2->can_take_two_way(name)) {
2927                         if (tw == NULL)
2928                                 tw = tw2;       /* found first one */
2929                         else
2930                                 fatal(_("two-way processor `%s' conflicts with previously installed two-way processor `%s'"),
2931                                                 tw2->name, tw->name);
2932                 }
2933         }
2934
2935         if (tw != NULL) {
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'"),
2940                                         tw->name, name);
2941                         return false;
2942                 }
2943                 iop_finish(rp->iop);
2944                 return true;
2945         }
2946
2947         return false;
2948 }
2949
2950 /*
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.
2957  *
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.
2962  *
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.
2975  *
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.
2979  *
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.
2983  *
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.
2989  */
2990
2991 /* iop_alloc --- allocate an IOBUF structure for an open fd */
2992
2993 static IOBUF *
2994 iop_alloc(int fd, const char *name, int errno_val)
2995 {
2996         IOBUF *iop;
2997
2998         emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
2999
3000         memset(iop, '\0', sizeof(IOBUF));
3001         iop->public.fd = fd;
3002         iop->public.name = name;
3003         iop->public.read_func = ( ssize_t(*)() ) read;
3004         iop->valid = false;
3005         iop->errcode = errno_val;
3006
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;
3013         }
3014 #endif
3015
3016         return iop;
3017 }
3018
3019 /* iop_finish --- finish setting up an IOBUF */
3020
3021 static IOBUF *
3022 iop_finish(IOBUF *iop)
3023 {
3024         bool isdir = false;
3025
3026         if (iop->public.fd != INVALID_HANDLE) {
3027                 if (os_isreadable(& iop->public, & isdir))
3028                         iop->valid = true;
3029                 else {
3030                         if (isdir)
3031                                 iop->errcode = EISDIR;
3032                         else {
3033                                 iop->errcode = EIO;
3034                                 /*
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.
3040                                  *
3041                                  * The fcntl call works for Windows, too.
3042                                  */
3043 #if defined(F_GETFL)
3044                                 if (fcntl(iop->public.fd, F_GETFL) >= 0)
3045 #endif
3046                                         (void) close(iop->public.fd);
3047                                 iop->public.fd = INVALID_HANDLE;
3048                         }
3049                         /*
3050                          * Don't close directories: after_beginfile(),
3051                          * special cases them.
3052                          */
3053                 }
3054         }
3055
3056         if (! iop->valid || iop->public.fd == INVALID_HANDLE)
3057                 return iop;
3058
3059         if (os_isatty(iop->public.fd))
3060                 iop->flag |= IOP_IS_TTY;
3061
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;
3072
3073         return iop;
3074 }
3075
3076 #define set_RT_to_null() \
3077         (void)(! do_traditional && (unref(RT_node->var_value), \
3078                            RT_node->var_value = dupnode(Nnull_string)))
3079
3080 #define set_RT(str, len) \
3081         (void)(! do_traditional && (unref(RT_node->var_value), \
3082                            RT_node->var_value = make_string(str, len)))
3083
3084 /*
3085  * grow_iop_buffer:
3086  *
3087  * grow must increase size of buffer, set end, make sure off and dataend
3088  * point at the right spot.
3089  */
3090
3091 static void
3092 grow_iop_buffer(IOBUF *iop)
3093 {
3094         size_t valid = iop->dataend - iop->off;
3095         size_t off = iop->off - iop->buf;
3096         size_t newsize;
3097
3098         /*
3099          * Lop off original extra two bytes, double the size,
3100          * add them back.
3101          */
3102         newsize = ((iop->size - 2) * 2) + 2;
3103
3104         /* Check for overflow */
3105         if (newsize <= iop->size)
3106                 fatal(_("could not allocate more input memory"));
3107
3108         /* Make sure there's room for a disk block */
3109         if (newsize - valid < iop->readsize)
3110                 newsize += iop->readsize + 2;
3111
3112         /* Check for overflow, again */
3113         if (newsize <= iop->size)
3114                 fatal(_("could not allocate more input memory"));
3115
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;
3121 }
3122
3123 /* Here are the routines. */
3124
3125 /* rs1scan --- scan for a single character record terminator */
3126
3127 static RECVALUE
3128 rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
3129 {
3130         char *bp;
3131         char rs;
3132 #if MBS_SUPPORT
3133         size_t mbclen = 0;
3134         mbstate_t mbs;
3135 #endif
3136
3137         memset(recm, '\0', sizeof(struct recmatch));
3138         rs = RS->stptr[0];
3139         *(iop->dataend) = rs;   /* set sentinel */
3140         recm->start = iop->off; /* beginning of record */
3141
3142         bp = iop->off;
3143         if (*state == INDATA)   /* skip over data we've already seen */
3144                 bp += iop->scanoff;
3145
3146 #if MBS_SUPPORT
3147         /*
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
3153          * 
3154          * Hi,
3155          * 
3156          * > Is there any way to make the following query to the current locale?
3157          * >
3158          * >    Given an 8-bit value, can this value ever appear as part of
3159          * >    a multibyte character?
3160          * 
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.
3166          * 
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.
3170          * 
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.
3177          * 
3178          * So it's safe to assume, but deserves a comment in the source.
3179          * 
3180          * Bruno
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
3186          * 
3187          * On Monday 23 June 2003 14:11, you wrote:
3188          * 
3189          * >       if (rs != '\n' && MB_CUR_MAX > 1) {
3190          * 
3191          * If you assume ASCII, you can even write
3192          * 
3193          *         if (rs >= 0x30 && MB_CUR_MAX > 1) {
3194          * 
3195          * (this catches also the space character) but if portability to EBCDIC
3196          * systems is desired, your code is fine as is.
3197          * 
3198          * Bruno
3199          */
3200         /* Thus, the check for \n here; big speedup ! */
3201         if (rs != '\n' && gawk_mb_cur_max > 1) {
3202                 int len = iop->dataend - bp;
3203                 int found = 0;
3204
3205                 memset(& mbs, 0, sizeof(mbstate_t));
3206                 do {
3207                         if (*bp == rs)
3208                                 found = 1;
3209                         if (is_valid_character(*bp))
3210                                 mbclen = 1;
3211                         else
3212                                 mbclen = mbrlen(bp, len, & mbs);
3213                         if (   mbclen == 1
3214                             || mbclen == (size_t) -1
3215                             || mbclen == (size_t) -2
3216                             || mbclen == 0) {
3217                                 /* We treat it as a single-byte character.  */
3218                                 mbclen = 1;
3219                         }
3220                         len -= mbclen;
3221                         bp += mbclen;
3222                 } while (len > 0 && ! found);
3223
3224                 /* Check that newline found isn't the sentinel. */
3225                 if (found && (bp - mbclen) < iop->dataend) {
3226                         /*
3227                          * Set len to what we have so far, in case this is
3228                          * all there is.
3229                          */
3230                         recm->len = bp - recm->start - mbclen;
3231                         recm->rt_start = bp - mbclen;
3232                         recm->rt_len = mbclen;
3233                         *state = NOSTATE;
3234                         return REC_OK;
3235                 } else {
3236                         /* also set len */
3237                         recm->len = bp - recm->start;
3238                         *state = INDATA;
3239                         iop->scanoff = bp - iop->off;
3240                         return NOTERM;
3241                 }
3242         }
3243 #endif
3244         while (*bp != rs)
3245                 bp++;
3246
3247         /* set len to what we have so far, in case this is all there is */
3248         recm->len = bp - recm->start;
3249
3250         if (bp < iop->dataend) {        /* found it in the buffer */
3251                 recm->rt_start = bp;
3252                 recm->rt_len = 1;
3253                 *state = NOSTATE;
3254                 return REC_OK;
3255         } else {
3256                 *state = INDATA;
3257                 iop->scanoff = bp - iop->off;
3258                 return NOTERM;
3259         }
3260 }
3261
3262 /* rsrescan --- search for a regex match in the buffer */
3263
3264 static RECVALUE
3265 rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
3266 {
3267         char *bp;
3268         size_t restart = 0, reend = 0;
3269         Regexp *RSre = RS_regexp;
3270         int regex_flags = RE_NEED_START;
3271
3272         memset(recm, '\0', sizeof(struct recmatch));
3273         recm->start = iop->off;
3274
3275         bp = iop->off;
3276         if (*state == INDATA)
3277                 bp += iop->scanoff;
3278
3279         if ((iop->flag & IOP_AT_START) == 0)
3280                 regex_flags |= RE_NO_BOL;
3281 again:
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;
3286                 return NOTERM;
3287         }
3288
3289         /* ok, we matched within the buffer, set start and end */
3290         restart = RESTART(RSre, iop->off);
3291         reend = REEND(RSre, iop->off);
3292
3293         /* case 2, null regex match, grow buffer, try again */
3294         if (restart == reend) {
3295                 *state = INDATA;
3296                 iop->scanoff = reend + 1;
3297                 /*
3298                  * If still room in buffer, skip over null match
3299                  * and restart search. Otherwise, return.
3300                  */
3301                 if (bp + iop->scanoff < iop->dataend) {
3302                         bp += iop->scanoff;
3303                         goto again;
3304                 }
3305                 recm->len = (bp - iop->off) + restart;
3306                 return NOTERM;
3307         }
3308
3309         /*
3310          * At this point, we have a non-empty match.
3311          *
3312          * First, fill in rest of data. The rest of the cases return
3313          * a record and terminator.
3314          */
3315         recm->len = restart;
3316         recm->rt_start = bp + restart;
3317         recm->rt_len = reend - restart;
3318         *state = NOSTATE;
3319
3320         /*
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
3324          *      else
3325          *              grow buffer, add more data, try again
3326          *      fi
3327          */
3328         if (iop->off + reend >= iop->dataend) {
3329                 if (reisstring(RS->stptr, RS->stlen, RSre, iop->off))
3330                         return REC_OK;
3331                 else
3332                         return TERMATEND;
3333         }
3334
3335         /*
3336          * 4. Match within xxx bytes of end & maybe islong re:
3337          *      return TERMNEAREND
3338          */
3339
3340         /*
3341          * case 4, match succeeded, but there may be more in
3342          * the next input buffer.
3343          *
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.
3347          *
3348          * This matches the "xyz" and ends up putting the
3349          * "abc" into the front of the next record. Ooops.
3350          *
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.
3356          */
3357
3358         /* succession of tests is easier to trace in GDB. */
3359         if (RSre->maybe_long) {
3360                 char *matchend = iop->off + reend;
3361
3362                 if (iop->dataend - matchend < RS->stlen)
3363                         return TERMNEAREND;
3364         }
3365
3366         return REC_OK;
3367 }
3368
3369 /* rsnullscan --- handle RS = "" */
3370
3371 static RECVALUE
3372 rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
3373 {
3374         char *bp;
3375
3376         if (*state == NOSTATE || *state == INLEADER)
3377                 memset(recm, '\0', sizeof(struct recmatch));
3378
3379         recm->start = iop->off;
3380
3381         bp = iop->off;
3382         if (*state != NOSTATE)
3383                 bp += iop->scanoff;
3384
3385         /* set sentinel */
3386         *(iop->dataend) = '\n';
3387
3388         if (*state == INTERM)
3389                 goto find_longest_terminator;
3390         else if (*state == INDATA)
3391                 goto scan_data;
3392         /* else
3393                 fall into things from beginning,
3394                 either NOSTATE or INLEADER */
3395
3396 /* skip_leading: */
3397         /* leading newlines are ignored */
3398         while (*bp == '\n' && bp < iop->dataend)
3399                 bp++;
3400
3401         if (bp >= iop->dataend) {       /* LOTS of leading newlines, sheesh. */
3402                 *state = INLEADER;
3403                 iop->scanoff = bp - iop->off;
3404                 return NOTERM;
3405         }
3406
3407         iop->off = recm->start = bp;    /* real start of record */
3408 scan_data:
3409         while (*bp++ != '\n')
3410                 continue;
3411
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;
3416                         recm->rt_len = 1;
3417                 }
3418                 *state = INDATA;
3419                 return NOTERM;
3420         }
3421
3422         /* found one newline before end of buffer, check next char */
3423         if (*bp != '\n')
3424                 goto scan_data;
3425
3426         /* we've now seen at least two newlines */
3427         *state = INTERM;
3428         recm->len = bp - iop->off - 1;
3429         recm->rt_start = bp - 1;
3430
3431 find_longest_terminator:
3432         /* find as many newlines as we can, to set RT */
3433         while (*bp == '\n' && bp < iop->dataend)
3434                 bp++;
3435
3436         recm->rt_len = bp - recm->rt_start;
3437         iop->scanoff = bp - iop->off;
3438
3439         if (bp >= iop->dataend)
3440                 return TERMATEND;
3441
3442         return REC_OK;
3443 }
3444
3445 /*
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.
3449  */
3450
3451 static int
3452 get_a_record(char **out,        /* pointer to pointer to data */
3453         IOBUF *iop,             /* input IOP */
3454         int *errcode)           /* pointer to error variable */
3455 {
3456         struct recmatch recm;
3457         SCANSTATE state;
3458         RECVALUE ret;
3459         int retval;
3460         NODE *rtval = NULL;
3461         static RECVALUE (*lastmatchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = NULL;
3462
3463         if (at_eof(iop) && no_data_left(iop))
3464                 return EOF;
3465
3466         if (read_can_timeout)
3467                 read_timeout = get_read_timeout(iop);
3468
3469         if (iop->public.get_record != NULL) {
3470                 char *rt_start;
3471                 size_t rt_len;
3472                 int rc = iop->public.get_record(out, &iop->public, errcode,
3473                                                 &rt_start, &rt_len);
3474                 if (rc == EOF)
3475                         iop->flag |= IOP_AT_EOF;
3476                 else {
3477                         if (rt_len != 0)
3478                                 set_RT(rt_start, rt_len);
3479                         else
3480                                 set_RT_to_null();
3481                 }
3482                 return rc;
3483         }
3484
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;
3490                         return EOF;
3491                 } else if (iop->count == -1) {
3492                         iop->flag |= IOP_AT_EOF; 
3493                         *errcode = errno;
3494                         return EOF;
3495                 } else {
3496                         iop->dataend = iop->buf + iop->count;
3497                         iop->off = iop->buf;
3498                 }
3499         }
3500
3501         /* loop through file to find a record */
3502         state = NOSTATE;
3503         for (;;) {
3504                 size_t dataend_off;
3505                 size_t room_left;
3506                 size_t amt_to_read;
3507
3508                 ret = (*matchrec)(iop, & recm, & state);
3509                 iop->flag &= ~IOP_AT_START;
3510                 if (ret == REC_OK)
3511                         break;
3512
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;
3519
3520                 /* adjust recm contents */
3521                 recm.start = iop->off;
3522                 if (recm.rt_start != NULL)
3523                         recm.rt_start = iop->off + recm.len;
3524
3525                 /* read more data, break if EOF */
3526 #ifndef MIN
3527 #define MIN(x, y) (x < y ? x : y)
3528 #endif
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);
3532
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;
3539
3540                         /* recalculate amt_to_read */
3541                         room_left = iop->end - iop->dataend - 1;
3542                         amt_to_read = MIN(iop->readsize, room_left);
3543                 }
3544                 while (amt_to_read + iop->readsize < room_left)
3545                         amt_to_read += iop->readsize;
3546
3547 #ifdef SSIZE_MAX
3548                 /*
3549                  * POSIX limits read to SSIZE_MAX. There are (bizarre)
3550                  * systems where this amount is small.
3551                  */
3552                 amt_to_read = MIN(amt_to_read, SSIZE_MAX);
3553 #endif
3554
3555                 iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read);
3556                 if (iop->count == -1) {
3557                         *errcode = errno;
3558                         iop->flag |= IOP_AT_EOF;
3559                         break;
3560                 } else if (iop->count == 0) {
3561                         /*
3562                          * hit EOF before matching RS, so end
3563                          * the record and set RT to ""
3564                          */
3565                         iop->flag |= IOP_AT_EOF;
3566                         break;
3567                 } else
3568                         iop->dataend += iop->count;
3569         }
3570
3571         /* set record, RT, return right value */
3572
3573         /*
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.
3578          */
3579         rtval = RT_node->var_value;
3580
3581         if (recm.rt_len == 0) {
3582                 set_RT_to_null();
3583                 lastmatchrec = NULL;
3584         } else {
3585                 assert(recm.rt_start != NULL);
3586                 /*
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
3590                  *
3591                  *      gawk '{ print }' /some/big/file
3592                  *
3593                  * Similarly, for rsnull case, if length of new RT is
3594                  * shorter than current RT, just bump length down in RT.
3595                  *
3596                  * Make sure that matchrec didn't change since the last
3597                  * check.  (Ugh, details, details, details.)
3598                  */
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);
3605                         /* else
3606                                 leave it alone */
3607                 } else if (matchrec == rsnullscan) {
3608                         if (rtval->stlen >= recm.rt_len) {
3609                                 rtval->stlen = recm.rt_len;
3610                                 free_wstr(rtval);
3611                         } else
3612                                 set_RT(recm.rt_start, recm.rt_len);
3613                 } else
3614                         set_RT(recm.rt_start, recm.rt_len);
3615         }
3616
3617         if (recm.len == 0) {
3618                 *out = NULL;
3619                 retval = 0;
3620         } else {
3621                 assert(recm.start != NULL);
3622                 *out = recm.start;
3623                 retval = recm.len;
3624         }
3625
3626         iop->off += recm.len + recm.rt_len;
3627
3628         if (recm.len == 0 && recm.rt_len == 0 && at_eof(iop))
3629                 return EOF;
3630         else
3631                 return retval;
3632 }
3633
3634 /* set_RS --- update things as appropriate when RS is set */
3635
3636 void
3637 set_RS()
3638 {
3639         static NODE *save_rs = NULL;
3640
3641         /*
3642          * Don't use cmp_nodes(), which pays attention to IGNORECASE.
3643          */
3644         if (save_rs
3645                 && RS_node->var_value->stlen == save_rs->stlen
3646                 && memcmp(RS_node->var_value->stptr, save_rs->stptr, save_rs->stlen) == 0) {
3647                 /*
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
3651                  * set_FS().
3652                  */
3653                 RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case);
3654                 goto set_FS;
3655         }
3656         unref(save_rs);
3657         save_rs = dupnode(RS_node->var_value);
3658         RS_is_null = false;
3659         RS = force_string(RS_node->var_value);
3660         /*
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.
3664          */
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;
3668
3669         if (RS->stlen == 0) {
3670                 RS_is_null = true;
3671                 matchrec = rsnullscan;
3672         } else if (RS->stlen > 1) {
3673                 static bool warned = false;
3674
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);
3678
3679                 matchrec = rsrescan;
3680
3681                 if (do_lint && ! warned) {
3682                         lintwarn(_("multicharacter value of `RS' is a gawk extension"));
3683                         warned = true;
3684                 }
3685         } else
3686                 matchrec = rs1scan;
3687 set_FS:
3688         if (current_field_sep() == Using_FS)
3689                 set_FS();
3690 }
3691
3692
3693 /* pty_vs_pipe --- return true if should use pty instead of pipes for `|&' */
3694
3695 /*
3696  * This works by checking if PROCINFO["command", "pty"] exists and is true.
3697  */
3698
3699 static int
3700 pty_vs_pipe(const char *command)
3701 {
3702 #ifdef HAVE_TERMIOS_H
3703         NODE *val;
3704
3705         if (PROCINFO_node == NULL)
3706                 return false;
3707         val = in_PROCINFO(command, "pty", NULL);
3708         if (val) {
3709                 if ((val->flags & MAYBE_NUM) != 0)
3710                         (void) force_number(val);
3711                 if ((val->flags & NUMBER) != 0)
3712                         return ! iszero(val);
3713                 else
3714                         return (val->stlen != 0);
3715         }
3716 #endif /* HAVE_TERMIOS_H */
3717         return false;
3718 }
3719
3720 /* iopflags2str --- make IOP flags printable */
3721
3722 const char *
3723 iopflags2str(int flag)
3724 {
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" },
3730                 { 0, NULL }
3731         };
3732
3733         return genflags2str(flag, values);
3734 }
3735
3736 /* free_rp --- release the memory used by rp */
3737
3738 static void
3739 free_rp(struct redirect *rp)
3740 {
3741         efree(rp->value);
3742         efree(rp);
3743 }
3744
3745 /* inetfile --- return true for a /inet special file, set other values */
3746
3747 static int
3748 inetfile(const char *str, int *length, int *family)
3749 {
3750         bool ret = false;
3751
3752         if (strncmp(str, "/inet/", 6) == 0) {
3753                 ret = true;
3754                 if (length != NULL)
3755                         *length = 6;
3756                 if (family != NULL)
3757                         *family = AF_UNSPEC;
3758         } else if (strncmp(str, "/inet4/", 7) == 0) {
3759                 ret = true;
3760                 if (length != NULL)
3761                         *length = 7;
3762                 if (family != NULL)
3763                         *family = AF_INET;
3764         } else if (strncmp(str, "/inet6/", 7) == 0) {
3765                 ret = true;
3766                 if (length != NULL)
3767                         *length = 7;
3768                 if (family != NULL)
3769                         *family = AF_INET6;
3770 #ifndef HAVE_GETADDRINFO
3771                 fatal(_("IPv6 communication is not supported"));
3772 #endif
3773         }
3774
3775         return ret;
3776 }
3777
3778 /*
3779  * in_PROCINFO --- return value for a PROCINFO element with
3780  *      SUBSEP seperated indices.
3781  */ 
3782
3783 static NODE *
3784 in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
3785 {
3786         char *str;
3787         size_t str_len;
3788         NODE *r, *sub = NULL; 
3789         NODE *subsep = SUBSEP_node->var_value;
3790
3791         /* full_idx is in+out parameter */
3792
3793         if (full_idx)
3794                 sub = *full_idx;
3795
3796         str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2);
3797         if (sub == NULL) {
3798                 emalloc(str, char *, str_len + 1, "in_PROCINFO");
3799                 sub = make_str_node(str, str_len, ALREADY_MALLOCED);
3800                 if (full_idx)
3801                         *full_idx = sub;
3802         } else if (str_len != sub->stlen) {
3803                 /* *full_idx != NULL */
3804
3805                 assert(sub->valref == 1);
3806                 erealloc(sub->stptr, char *, str_len + 1, "in_PROCINFO");
3807                 sub->stlen = str_len;
3808         }
3809
3810         sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen,
3811                         subsep->stptr, pidx2);
3812         r = in_array(PROCINFO_node, sub);
3813         if (! full_idx)
3814                 unref(sub);
3815         return r;
3816 }
3817
3818
3819 /* get_read_timeout --- get timeout in milliseconds for reading */
3820
3821 static long
3822 get_read_timeout(IOBUF *iop)
3823 {
3824         long tmout = 0;
3825
3826         if (PROCINFO_node != NULL) {
3827                 const char *name = iop->public.name;
3828                 NODE *val = NULL;
3829                 static NODE *full_idx = NULL;
3830                 static const char *last_name = NULL;
3831
3832                 /*
3833                  * Do not re-construct the full index when last redirection
3834                  * string is the same as the current; "efficiency_hack++".
3835                  */
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);
3843
3844                 if (val != NULL) {
3845                         (void) force_number(val);
3846                         tmout = get_number_si(val);
3847                 }
3848         } else
3849                 tmout = read_default_timeout;   /* initialized from env. variable in init_io() */
3850
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;
3854
3855         return tmout;
3856 }
3857
3858 /*
3859  * read_with_timeout --- read with a timeout, return failure
3860  *      if no data is available within the timeout period.
3861  */
3862
3863 static ssize_t
3864 read_with_timeout(int fd, char *buf, size_t size)
3865 {
3866 #if ! defined(VMS)
3867         fd_set readfds;
3868         struct timeval tv;
3869 #ifdef __MINGW32__
3870         /*
3871          * Only sockets can be read with a timeout.  Also, the FD_*
3872          * macros work on SOCKET type, not on int file descriptors.
3873          */
3874         SOCKET s = valid_socket(fd);
3875
3876         if (!s)
3877                 return read(fd, buf, size);
3878 #else
3879         int s = fd;
3880 #endif
3881
3882         tv.tv_sec = read_timeout / 1000;
3883         tv.tv_usec = 1000 * (read_timeout - 1000 * tv.tv_sec);
3884
3885         FD_ZERO(& readfds);
3886         FD_SET(s, & readfds);
3887
3888         errno = 0;
3889         /*
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.
3893          */
3894         if (select(fd + 1, & readfds, NULL, NULL, & tv) < 0)
3895                 return -1;
3896
3897         if (FD_ISSET(s, & readfds))
3898                 return read(fd, buf, size);
3899         /* else
3900                 timed out */
3901
3902         /* Set a meaningful errno */
3903 #ifdef ETIMEDOUT
3904         errno = ETIMEDOUT;
3905 #else
3906         errno = EAGAIN;
3907 #endif
3908         return -1;
3909 #else  /* VMS */
3910         return read(fd, buf, size);
3911 #endif  /* VMS */
3912 }
3913
3914 /*
3915  * Dummy pass through functions for default output.
3916  */
3917
3918 /* gawk_fwrite --- like fwrite */
3919
3920 static size_t
3921 gawk_fwrite(const void *buf, size_t size, size_t count, FILE *fp, void *opaque)
3922 {
3923         (void) opaque;
3924
3925         return fwrite(buf, size, count, fp);
3926 }
3927
3928 static int
3929 gawk_fflush(FILE *fp, void *opaque)
3930 {
3931         (void) opaque;
3932
3933         return fflush(fp);
3934 }
3935
3936 static int
3937 gawk_ferror(FILE *fp, void *opaque)
3938 {
3939         (void) opaque;
3940
3941         return ferror(fp);
3942 }
3943
3944 static int
3945 gawk_fclose(FILE *fp, void *opaque)
3946 {
3947         int result;
3948 #ifdef __MINGW32__
3949         SOCKET s = valid_socket (fileno(fp));
3950 #endif
3951         (void) opaque;
3952
3953         result =  fclose(fp);
3954 #ifdef __MINGW32__
3955         if (s && closesocket(s) == SOCKET_ERROR)
3956                 result = -1;
3957 #endif
3958         return result;
3959 }
3960
3961
3962 /* init_output_wrapper --- initialize the output wrapper */
3963
3964 static void
3965 init_output_wrapper(awk_output_buf_t *outbuf)
3966 {
3967         outbuf->name = NULL;
3968         outbuf->mode = NULL;
3969         outbuf->fp = 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;
3976 }