00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "awk.h"
00027
00028 #ifdef HAVE_SYS_PARAM_H
00029 #undef RE_DUP_MAX
00030 #include <sys/param.h>
00031 #endif
00032
00033 #ifndef O_RDONLY
00034 #include <fcntl.h>
00035 #endif
00036 #ifndef O_ACCMODE
00037 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
00038 #endif
00039
00040 #ifdef HAVE_TERMIOS_H
00041 #include <termios.h>
00042 #endif
00043 #ifdef HAVE_STROPTS_H
00044 #include <stropts.h>
00045 #endif
00046
00047 #ifdef HAVE_SOCKETS
00048 #ifdef HAVE_SYS_SOCKET_H
00049 #include <sys/socket.h>
00050 #else
00051 #include <socket.h>
00052 #endif
00053 #ifdef HAVE_NETINET_IN_H
00054 #include <netinet/in.h>
00055 #else
00056 #include <in.h>
00057 #endif
00058 #ifdef HAVE_NETDB_H
00059 #include <netdb.h>
00060 #endif
00061 #endif
00062
00063 #ifdef __EMX__
00064 #include <process.h>
00065 #endif
00066
00067 #ifndef ENFILE
00068 #define ENFILE EMFILE
00069 #endif
00070
00071 extern int MRL;
00072
00073 #ifdef HAVE_SOCKETS
00074 enum inet_prot { INET_NONE, INET_TCP, INET_UDP, INET_RAW };
00075
00076 #ifndef SHUT_RD
00077 #define SHUT_RD 0
00078 #endif
00079
00080 #ifndef SHUT_WR
00081 #define SHUT_WR 1
00082 #endif
00083
00084 #ifndef SHUT_RDWR
00085 #define SHUT_RDWR 2
00086 #endif
00087
00088 #endif
00089
00090 #ifdef atarist
00091 #include <stddef.h>
00092 #endif
00093
00094 #if defined(GAWK_AIX)
00095 #undef TANDEM
00096 #undef MSDOS
00097 #undef WIN32
00098 #endif
00099
00100 #if defined(MSDOS) || defined(WIN32) || defined(TANDEM)
00101 #define PIPES_SIMULATED
00102 #endif
00103
00104 typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
00105
00106
00107
00108
00109
00110 #define at_eof(iop) ((iop->flag & IOP_AT_EOF) != 0)
00111 #define has_no_data(iop) (iop->dataend == NULL)
00112 #define no_data_left(iop) (iop->off >= iop->dataend)
00113
00114
00115
00116
00117
00118
00119
00120
00121 typedef enum recvalues {
00122 REC_OK,
00123 NOTERM,
00124 TERMATEND,
00125 TERMNEAREND,
00126 } RECVALUE;
00127
00128
00129
00130
00131
00132
00133 typedef enum scanstate {
00134 NOSTATE,
00135 INLEADER,
00136 INDATA,
00137 INTERM,
00138 } SCANSTATE;
00139
00140
00141
00142
00143
00144 struct recmatch {
00145 char *start;
00146 size_t len;
00147 char *rt_start;
00148 size_t rt_len;
00149 };
00150
00151 static IOBUF *nextfile P((int skipping));
00152 static int inrec P((IOBUF *iop));
00153 static int iop_close P((IOBUF *iop));
00154 struct redirect *redirect P((NODE *tree, int *errflg));
00155 static void close_one P((void));
00156 static int close_redir P((struct redirect *rp, int exitwarn, two_way_close_type how));
00157 #ifndef PIPES_SIMULATED
00158 static int wait_any P((int interesting));
00159 #endif
00160 static IOBUF *gawk_popen P((const char *cmd, struct redirect *rp));
00161 static IOBUF *iop_open P((const char *file, const char *how, IOBUF *buf));
00162 static IOBUF *iop_alloc P((int fd, const char *name, IOBUF *buf));
00163 static int gawk_pclose P((struct redirect *rp));
00164 static int do_pathopen P((const char *file));
00165 static int str2mode P((const char *mode));
00166 static void spec_setup P((IOBUF *iop, int len, int allocate));
00167 static int specfdopen P((IOBUF *iop, const char *name, const char *mode));
00168 static int pidopen P((IOBUF *iop, const char *name, const char *mode));
00169 static int useropen P((IOBUF *iop, const char *name, const char *mode));
00170 static int two_way_open P((const char *str, struct redirect *rp));
00171 static int pty_vs_pipe P((const char *command));
00172
00173 static RECVALUE rs1scan P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state));
00174 static RECVALUE rsnullscan P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state));
00175 static RECVALUE rsrescan P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state));
00176
00177 static RECVALUE (*matchrec) P((IOBUF *iop, struct recmatch *recm, SCANSTATE *state)) = rs1scan;
00178
00179 static int get_a_record P((char **out, IOBUF *iop, int *errcode));
00180
00181 #if defined(HAVE_POPEN_H)
00182 #include "popen.h"
00183 #endif
00184
00185 static struct redirect *red_head = NULL;
00186 static NODE *RS;
00187 static Regexp *RS_re_yes_case;
00188 static Regexp *RS_re_no_case;
00189 static Regexp *RS_regexp;
00190
00191 int RS_is_null;
00192
00193 extern int output_is_tty;
00194 extern NODE *ARGC_node;
00195 extern NODE *ARGV_node;
00196 extern NODE *ARGIND_node;
00197 extern NODE *ERRNO_node;
00198 extern NODE **fields_arr;
00199
00200 static jmp_buf filebuf;
00201
00202 #if defined(MSDOS) || defined(OS2) || defined(WIN32) \
00203 || defined(__EMX__) || defined(__CYGWIN__)
00204 static const char *
00205 binmode(const char *mode)
00206 {
00207 switch (mode[0]) {
00208 case 'r':
00209 if ((BINMODE & 1) != 0)
00210 mode = "rb";
00211 break;
00212 case 'w':
00213 case 'a':
00214 if ((BINMODE & 2) != 0)
00215 mode = (mode[0] == 'w' ? "wb" : "ab");
00216 break;
00217 }
00218 return mode;
00219 }
00220 #else
00221 #define binmode(mode) (mode)
00222 #endif
00223
00224 #ifdef VMS
00225
00226
00227 static int vmsrtl_fileno P((FILE *));
00228 static int vmsrtl_fileno(fp) FILE *fp; { return fileno(fp); }
00229 #undef fileno
00230 #define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1)
00231 #endif
00232
00233
00234
00235 void
00236 do_nextfile()
00237 {
00238 (void) nextfile(TRUE);
00239 longjmp(filebuf, 1);
00240 }
00241
00242
00243
00244 static IOBUF *
00245 nextfile(int skipping)
00246 {
00247 static long i = 1;
00248 static int files = 0;
00249 NODE *arg;
00250 static IOBUF *curfile = NULL;
00251 static IOBUF mybuf;
00252 const char *fname;
00253
00254 if (skipping) {
00255 if (curfile != NULL)
00256 iop_close(curfile);
00257 curfile = NULL;
00258 return NULL;
00259 }
00260 if (curfile != NULL) {
00261 if (at_eof(curfile)) {
00262 (void) iop_close(curfile);
00263 curfile = NULL;
00264 } else
00265 return curfile;
00266 }
00267 for (; i < (long) (ARGC_node->lnode->numbr); i++) {
00268 arg = *assoc_lookup(ARGV_node, tmp_number((AWKNUM) i), FALSE);
00269 if (arg->stlen == 0)
00270 continue;
00271 arg->stptr[arg->stlen] = '\0';
00272 if (! do_traditional) {
00273 unref(ARGIND_node->var_value);
00274 ARGIND_node->var_value = make_number((AWKNUM) i);
00275 }
00276 if (! arg_assign(arg->stptr, FALSE)) {
00277 files++;
00278 fname = arg->stptr;
00279 curfile = iop_open(fname, binmode("r"), &mybuf);
00280 if (curfile == NULL)
00281 goto give_up;
00282 curfile->flag |= IOP_NOFREE_OBJ;
00283
00284 unref(FILENAME_node->var_value);
00285 FILENAME_node->var_value = dupnode(arg);
00286 FNR = 0;
00287 i++;
00288 break;
00289 }
00290 }
00291 if (files == 0) {
00292 files++;
00293
00294
00295 FILENAME_node->var_value = make_string("-", 1);
00296 fname = "-";
00297 curfile = iop_open(fname, binmode("r"), &mybuf);
00298 if (curfile == NULL)
00299 goto give_up;
00300 curfile->flag |= IOP_NOFREE_OBJ;
00301 }
00302 return curfile;
00303
00304 give_up:
00305 fatal(_("cannot open file `%s' for reading (%s)"),
00306 fname, strerror(errno));
00307
00308 return 0;
00309 }
00310
00311
00312
00313 void
00314 set_FNR()
00315 {
00316 FNR = (long) FNR_node->var_value->numbr;
00317 }
00318
00319
00320
00321 void
00322 set_NR()
00323 {
00324 NR = (long) NR_node->var_value->numbr;
00325 }
00326
00327
00328
00329 static int
00330 inrec(IOBUF *iop)
00331 {
00332 char *begin;
00333 register int cnt;
00334 int retval = 0;
00335
00336 if (at_eof(iop) && no_data_left(iop))
00337 cnt = EOF;
00338 else if ((iop->flag & IOP_CLOSED) != 0)
00339 cnt = EOF;
00340 else
00341 cnt = get_a_record(&begin, iop, NULL);
00342
00343 if (cnt == EOF) {
00344 cnt = 0;
00345 retval = 1;
00346 } else {
00347 NR += 1;
00348 FNR += 1;
00349 set_record(begin, cnt);
00350 }
00351
00352 return retval;
00353 }
00354
00355
00356
00357 static int
00358 iop_close(IOBUF *iop)
00359 {
00360 int ret;
00361
00362 if (iop == NULL)
00363 return 0;
00364 errno = 0;
00365
00366 iop->flag &= ~IOP_AT_EOF;
00367 iop->flag |= IOP_CLOSED;
00368 iop->dataend = NULL;
00369 #ifdef _CRAY
00370
00371 if (iop->fd < 3)
00372 ret = 0;
00373 else
00374 #endif
00375
00376 if ((iop->flag & IOP_IS_INTERNAL) != 0) {
00377 iop->off = iop->buf;
00378 iop->end = iop->buf + strlen(iop->buf);
00379 iop->count = 0;
00380 return 0;
00381 }
00382
00383
00384 if (iop->fd == fileno(stdin)
00385 || iop->fd == fileno(stdout)
00386 || iop->fd == fileno(stderr))
00387 ret = 0;
00388 else
00389 ret = close(iop->fd);
00390
00391 if (ret == -1)
00392 warning(_("close of fd %d (`%s') failed (%s)"), iop->fd,
00393 iop->name, strerror(errno));
00394 if ((iop->flag & IOP_NO_FREE) == 0) {
00395
00396
00397
00398
00399
00400 if (iop->buf) {
00401 if ((fields_arr[0]->stptr >= iop->buf)
00402 && (fields_arr[0]->stptr < (iop->buf + iop->size))) {
00403 NODE *t;
00404
00405 t = make_string(fields_arr[0]->stptr,
00406 fields_arr[0]->stlen);
00407 unref(fields_arr[0]);
00408 fields_arr[0] = t;
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 }
00419 free(iop->buf);
00420 iop->buf = NULL;
00421 }
00422 if ((iop->flag & IOP_NOFREE_OBJ) == 0)
00423 free((char *) iop);
00424 }
00425 return ret == -1 ? 1 : 0;
00426 }
00427
00428
00429
00430 void
00431 do_input()
00432 {
00433 IOBUF *iop;
00434 extern int exiting;
00435 int rval1, rval2, rval3;
00436
00437 (void) setjmp(filebuf);
00438
00439 while ((iop = nextfile(FALSE)) != NULL) {
00440
00441
00442
00443
00444
00445
00446
00447 rval1 = inrec(iop);
00448 if (rval1 == 0) {
00449 for (;;) {
00450 rval2 = rval3 = -1;
00451 rval2 = interpret(expression_value);
00452 if (rval2 != 0)
00453 rval3 = inrec(iop);
00454 if (rval2 == 0 || rval3 != 0)
00455 break;
00456 }
00457 }
00458 if (exiting)
00459 break;
00460 }
00461 }
00462
00463
00464
00465 const char *
00466 redflags2str(int flags)
00467 {
00468 static const struct flagtab redtab[] = {
00469 { RED_FILE, "RED_FILE" },
00470 { RED_PIPE, "RED_PIPE" },
00471 { RED_READ, "RED_READ" },
00472 { RED_WRITE, "RED_WRITE" },
00473 { RED_APPEND, "RED_APPEND" },
00474 { RED_NOBUF, "RED_NOBUF" },
00475 { RED_EOF, "RED_EOF" },
00476 { RED_TWOWAY, "RED_TWOWAY" },
00477 { RED_PTY, "RED_PTY" },
00478 { RED_SOCKET, "RED_SOCKET" },
00479 { RED_TCP, "RED_TCP" },
00480 { 0, NULL }
00481 };
00482
00483 return genflags2str(flags, redtab);
00484 }
00485
00486
00487
00488 struct redirect *
00489 redirect(NODE *tree, int *errflg)
00490 {
00491 register NODE *tmp;
00492 register struct redirect *rp;
00493 register char *str;
00494 int tflag = 0;
00495 int outflag = 0;
00496 const char *direction = "to";
00497 const char *mode;
00498 int fd;
00499 const char *what = NULL;
00500
00501 switch (tree->type) {
00502 case Node_redirect_append:
00503 tflag = RED_APPEND;
00504
00505 case Node_redirect_output:
00506 outflag = (RED_FILE|RED_WRITE);
00507 tflag |= outflag;
00508 if (tree->type == Node_redirect_output)
00509 what = ">";
00510 else
00511 what = ">>";
00512 break;
00513 case Node_redirect_pipe:
00514 tflag = (RED_PIPE|RED_WRITE);
00515 what = "|";
00516 break;
00517 case Node_redirect_pipein:
00518 tflag = (RED_PIPE|RED_READ);
00519 what = "|";
00520 break;
00521 case Node_redirect_input:
00522 tflag = (RED_FILE|RED_READ);
00523 what = "<";
00524 break;
00525 case Node_redirect_twoway:
00526 tflag = (RED_READ|RED_WRITE|RED_TWOWAY);
00527 what = "|&";
00528 break;
00529 default:
00530 fatal(_("invalid tree type %s in redirect()"),
00531 nodetype2str(tree->type));
00532 break;
00533 }
00534 tmp = tree_eval(tree->subnode);
00535 if (do_lint && (tmp->flags & STRCUR) == 0)
00536 lintwarn(_("expression in `%s' redirection only has numeric value"),
00537 what);
00538 tmp = force_string(tmp);
00539 str = tmp->stptr;
00540
00541 if (str == NULL || *str == '\0')
00542 fatal(_("expression for `%s' redirection has null string value"),
00543 what);
00544
00545 if (do_lint
00546 && (STREQN(str, "0", tmp->stlen) || STREQN(str, "1", tmp->stlen)))
00547 lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"), str, what);
00548
00549 #ifdef HAVE_SOCKETS
00550 if (STREQN(str, "/inet/", 6)) {
00551 tflag |= RED_SOCKET;
00552 if (STREQN(str + 6, "tcp/", 4))
00553 tflag |= RED_TCP;
00554 }
00555 #endif
00556
00557 for (rp = red_head; rp != NULL; rp = rp->next) {
00558 if (strlen(rp->value) == tmp->stlen
00559 && STREQN(rp->value, str, tmp->stlen)
00560 && ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag
00561 || (outflag != 0
00562 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) {
00563
00564 int rpflag = (rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY));
00565 int newflag = (tflag & ~(RED_NOBUF|RED_EOF|RED_PTY));
00566
00567 if (do_lint && rpflag != newflag)
00568 lintwarn(
00569 _("unnecessary mixing of `>' and `>>' for file `%.*s'"),
00570 tmp->stlen, rp->value);
00571
00572 break;
00573 }
00574 }
00575
00576 if (rp == NULL) {
00577 emalloc(rp, struct redirect *, sizeof(struct redirect),
00578 "redirect");
00579 emalloc(str, char *, tmp->stlen+1, "redirect");
00580 memcpy(str, tmp->stptr, tmp->stlen);
00581 str[tmp->stlen] = '\0';
00582 rp->value = str;
00583 rp->flag = tflag;
00584 rp->fp = NULL;
00585 rp->iop = NULL;
00586 rp->pid = 0;
00587 rp->status = 0;
00588
00589 if (red_head != NULL)
00590 red_head->prev = rp;
00591 rp->prev = NULL;
00592 rp->next = red_head;
00593 red_head = rp;
00594 } else
00595 str = rp->value;
00596
00597 while (rp->fp == NULL && rp->iop == NULL) {
00598 if (rp->flag & RED_EOF)
00599
00600
00601
00602
00603 return rp;
00604 mode = NULL;
00605 errno = 0;
00606 switch (tree->type) {
00607 case Node_redirect_output:
00608 mode = binmode("w");
00609 if ((rp->flag & RED_USED) != 0)
00610 mode = (rp->mode[1] == 'b') ? "ab" : "a";
00611 break;
00612 case Node_redirect_append:
00613 mode = binmode("a");
00614 break;
00615 case Node_redirect_pipe:
00616
00617 (void) flush_io();
00618
00619 os_restore_mode(fileno(stdin));
00620 if ((rp->fp = popen(str, binmode("w"))) == NULL)
00621 fatal(_("can't open pipe `%s' for output (%s)"),
00622 str, strerror(errno));
00623
00624 os_close_on_exec(fileno(rp->fp), str, "pipe", "to");
00625 rp->flag |= RED_NOBUF;
00626 break;
00627 case Node_redirect_pipein:
00628 direction = "from";
00629 if (gawk_popen(str, rp) == NULL)
00630 fatal(_("can't open pipe `%s' for input (%s)"),
00631 str, strerror(errno));
00632 break;
00633 case Node_redirect_input:
00634 direction = "from";
00635 rp->iop = iop_open(str, binmode("r"), NULL);
00636 break;
00637 case Node_redirect_twoway:
00638 direction = "to/from";
00639 if (! two_way_open(str, rp)) {
00640 #ifdef HAVE_SOCKETS
00641
00642 if (STREQN(str, "/inet/", 6))
00643 fatal(_("can't open two way socket `%s' for input/output (%s)"),
00644 str, strerror(errno));
00645 else
00646 #endif
00647 fatal(_("can't open two way pipe `%s' for input/output (%s)"),
00648 str, strerror(errno));
00649 }
00650 break;
00651 default:
00652 cant_happen();
00653 }
00654 if (mode != NULL) {
00655 errno = 0;
00656 fd = devopen(str, mode);
00657 if (fd > INVALID_HANDLE) {
00658 if (fd == fileno(stdin))
00659 rp->fp = stdin;
00660 else if (fd == fileno(stdout))
00661 rp->fp = stdout;
00662 else if (fd == fileno(stderr))
00663 rp->fp = stderr;
00664 else {
00665 #if defined(F_GETFL) && defined(O_APPEND)
00666 int fd_flags;
00667
00668 fd_flags = fcntl(fd, F_GETFL);
00669 if (fd_flags != -1 && (fd_flags & O_APPEND) == O_APPEND)
00670 rp->fp = fdopen(fd, binmode("a"));
00671 else
00672 #endif
00673 rp->fp = fdopen(fd, (const char *) mode);
00674 rp->mode = (const char *) mode;
00675
00676 if (rp->fp == NULL)
00677 close(fd);
00678 }
00679 if (rp->fp != NULL && isatty(fd))
00680 rp->flag |= RED_NOBUF;
00681
00682 if (red_head != rp) {
00683 if ((rp->prev->next = rp->next) != NULL)
00684 rp->next->prev = rp->prev;
00685 red_head->prev = rp;
00686 rp->prev = NULL;
00687 rp->next = red_head;
00688 red_head = rp;
00689 }
00690 }
00691 }
00692 if (rp->fp == NULL && rp->iop == NULL) {
00693
00694 if (errno == EMFILE || errno == ENFILE)
00695 close_one();
00696 #if defined __MINGW32__ || defined __sun
00697 else if (errno == 0)
00698 close_one();
00699 #endif
00700 #ifdef VMS
00701
00702
00703 #define SS$_EXQUOTA 0x001C
00704 else if (errno == EIO && vaxc$errno == SS$_EXQUOTA)
00705 close_one();
00706 #endif
00707 else {
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 if (errflg != NULL)
00718 *errflg = errno;
00719 if (tree->type == Node_redirect_output
00720 || tree->type == Node_redirect_append) {
00721
00722 if (*direction == 'f')
00723 fatal(_("can't redirect from `%s' (%s)"),
00724 str, strerror(errno));
00725 else
00726 fatal(_("can't redirect to `%s' (%s)"),
00727 str, strerror(errno));
00728 } else {
00729 free_temp(tmp);
00730 return NULL;
00731 }
00732 }
00733 }
00734 }
00735 free_temp(tmp);
00736 return rp;
00737 }
00738
00739
00740
00741 struct redirect *
00742 getredirect(const char *str, int len)
00743 {
00744 struct redirect *rp;
00745
00746 for (rp = red_head; rp != NULL; rp = rp->next)
00747 if (strlen(rp->value) == len && STREQN(rp->value, str, len))
00748 return rp;
00749
00750 return NULL;
00751 }
00752
00753
00754
00755 static void
00756 close_one()
00757 {
00758 register struct redirect *rp;
00759 register struct redirect *rplast = NULL;
00760
00761 static short warned = FALSE;
00762
00763 if (do_lint && ! warned) {
00764 warned = TRUE;
00765 lintwarn(_("reached system limit for open files: starting to multiplex file descriptors"));
00766 }
00767
00768
00769 for (rp = red_head; rp != NULL; rp = rp->next)
00770 rplast = rp;
00771
00772 for (rp = rplast; rp != NULL; rp = rp->prev)
00773 if (rp->fp != NULL && (rp->flag & RED_FILE) != 0) {
00774 rp->flag |= RED_USED;
00775 errno = 0;
00776 if ( fclose(rp->fp) != 0)
00777 warning(_("close of `%s' failed (%s)."),
00778 rp->value, strerror(errno));
00779 rp->fp = NULL;
00780 break;
00781 }
00782 if (rp == NULL)
00783
00784 fatal(_("too many pipes or input files open"));
00785 }
00786
00787
00788
00789 NODE *
00790 do_close(NODE *tree)
00791 {
00792 NODE *tmp, *tmp2;
00793 register struct redirect *rp;
00794 two_way_close_type how = CLOSE_ALL;
00795
00796 tmp = force_string(tree_eval(tree->lnode));
00797
00798 if (tree->rnode != NULL) {
00799
00800
00801 tmp2 = force_string(tree->rnode->lnode);
00802 if (strcasecmp(tmp2->stptr, "to") == 0)
00803 how = CLOSE_TO;
00804 else if (strcasecmp(tmp2->stptr, "from") == 0)
00805 how = CLOSE_FROM;
00806 else
00807 fatal(_("close: second argument must be `to' or `from'"));
00808 free_temp(tmp2);
00809 }
00810
00811 for (rp = red_head; rp != NULL; rp = rp->next) {
00812 if (strlen(rp->value) == tmp->stlen
00813 && STREQN(rp->value, tmp->stptr, tmp->stlen))
00814 break;
00815 }
00816
00817 if (rp == NULL) {
00818 char *cp;
00819
00820 if (do_lint)
00821 lintwarn(_("close: `%.*s' is not an open file, pipe or co-process"),
00822 tmp->stlen, tmp->stptr);
00823
00824
00825 cp = _("close of redirection that was never opened");
00826 unref(ERRNO_node->var_value);
00827 ERRNO_node->var_value = make_string(cp, strlen(cp));
00828
00829 free_temp(tmp);
00830 return tmp_number((AWKNUM) -1.0);
00831 }
00832 free_temp(tmp);
00833 fflush(stdout);
00834 tmp = tmp_number((AWKNUM) close_redir(rp, FALSE, how));
00835 rp = NULL;
00836
00837
00838
00839
00840
00841
00842 if (do_posix) {
00843 free_temp(tmp);
00844 return tmp_number((AWKNUM) 0);
00845 }
00846 return tmp;
00847 }
00848
00849
00850
00851 static int
00852 close_redir(register struct redirect *rp, int exitwarn, two_way_close_type how)
00853 {
00854 int status = 0;
00855
00856 if (rp == NULL)
00857 return 0;
00858 if (rp->fp == stdout || rp->fp == stderr)
00859 return 0;
00860
00861 if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL)
00862 lintwarn(_("close: redirection `%s' not opened with `|&', second argument ignored"),
00863 rp->value);
00864
00865 errno = 0;
00866 if ((rp->flag & RED_TWOWAY) != 0) {
00867
00868 if ((how == CLOSE_ALL || how == CLOSE_TO) && rp->fp != NULL) {
00869 #ifdef HAVE_SOCKETS
00870 if ((rp->flag & RED_TCP) != 0)
00871 (void) shutdown(fileno(rp->fp), SHUT_WR);
00872 #endif
00873
00874 if ((rp->flag & RED_PTY) != 0) {
00875 fwrite("\004\n", sizeof("\004\n") - 1, 1, rp->fp);
00876 fflush(rp->fp);
00877 }
00878 status = fclose(rp->fp);
00879 rp->fp = NULL;
00880 }
00881
00882
00883 if (how == CLOSE_ALL || how == CLOSE_FROM) {
00884 if ((rp->flag & RED_SOCKET) != 0 && rp->iop != NULL) {
00885 #ifdef HAVE_SOCKETS
00886 if ((rp->flag & RED_TCP) != 0)
00887 (void) shutdown(rp->iop->fd, SHUT_RD);
00888 #endif
00889 (void) iop_close(rp->iop);
00890 } else
00891 status = gawk_pclose(rp);
00892
00893 rp->iop = NULL;
00894 }
00895 } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) {
00896 status = pclose(rp->fp);
00897 if ((BINMODE & 1) != 0)
00898 os_setbinmode(fileno(stdin), O_BINARY);
00899
00900 rp->fp = NULL;
00901 } else if (rp->fp != NULL) {
00902 status = fclose(rp->fp);
00903 rp->fp = NULL;
00904 } else if (rp->iop != NULL) {
00905 if ((rp->flag & RED_PIPE) != 0)
00906 status = gawk_pclose(rp);
00907
00908 else {
00909 status = iop_close(rp->iop);
00910 rp->iop = NULL;
00911 }
00912 }
00913
00914
00915 if (status != 0) {
00916 char *s = strerror(errno);
00917
00918
00919
00920
00921
00922 if (do_lint) {
00923 if ((rp->flag & RED_PIPE) != 0)
00924 lintwarn(_("failure status (%d) on pipe close of `%s' (%s)"),
00925 status, rp->value, s);
00926 else
00927 lintwarn(_("failure status (%d) on file close of `%s' (%s)"),
00928 status, rp->value, s);
00929 }
00930
00931 if (! do_traditional) {
00932
00933 update_ERRNO();
00934 }
00935 }
00936
00937 if (exitwarn) {
00938
00939
00940
00941
00942
00943
00944
00945 if ((rp->flag & RED_SOCKET) != 0)
00946 warning(_("no explicit close of socket `%s' provided"),
00947 rp->value);
00948 else if ((rp->flag & RED_TWOWAY) != 0)
00949 warning(_("no explicit close of co-process `%s' provided"),
00950 rp->value);
00951 else if ((rp->flag & RED_PIPE) != 0)
00952 warning(_("no explicit close of pipe `%s' provided"),
00953 rp->value);
00954 else
00955 warning(_("no explicit close of file `%s' provided"),
00956 rp->value);
00957 }
00958
00959
00960 if (how == CLOSE_ALL || (rp->iop == NULL && rp->fp == NULL)) {
00961 if (rp->next != NULL)
00962 rp->next->prev = rp->prev;
00963 if (rp->prev != NULL)
00964 rp->prev->next = rp->next;
00965 else
00966 red_head = rp->next;
00967 free(rp->value);
00968 free((char *) rp);
00969 }
00970
00971 return status;
00972 }
00973
00974
00975
00976 int
00977 flush_io()
00978 {
00979 register struct redirect *rp;
00980 int status = 0;
00981
00982 errno = 0;
00983 if (fflush(stdout)) {
00984 warning(_("error writing standard output (%s)"), strerror(errno));
00985 status++;
00986 }
00987 if (fflush(stderr)) {
00988 warning(_("error writing standard error (%s)"), strerror(errno));
00989 status++;
00990 }
00991 for (rp = red_head; rp != NULL; rp = rp->next)
00992
00993 if ((rp->flag & RED_WRITE) && rp->fp != NULL) {
00994 if (fflush(rp->fp)) {
00995 if (rp->flag & RED_PIPE)
00996 warning(_("pipe flush of `%s' failed (%s)."),
00997 rp->value, strerror(errno));
00998 else if (rp->flag & RED_TWOWAY)
00999 warning(_("co-process flush of pipe to `%s' failed (%s)."),
01000 rp->value, strerror(errno));
01001 else
01002 warning(_("file flush of `%s' failed (%s)."),
01003 rp->value, strerror(errno));
01004 status++;
01005 }
01006 }
01007 if (status != 0)
01008 status = -1;
01009 return status;
01010 }
01011
01012
01013
01014 int
01015 close_io()
01016 {
01017 register struct redirect *rp;
01018 register struct