home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / gawk213b / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-29  |  19.2 KB  |  847 lines

  1. /*
  2.  * io.c - routines for dealing with input and output and records
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming 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 1, or (at your option)
  14.  * 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 GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. #ifndef O_RDONLY
  29. #include <fcntl.h>
  30. #endif
  31.  
  32. #ifndef atarist
  33. #define INVALID_HANDLE (-1)
  34. #else
  35. #define INVALID_HANDLE  (__SMALLEST_VALID_HANDLE - 1)
  36. #endif
  37.  
  38. static IOBUF *nextfile P((void));
  39. static int inrec P((IOBUF *iop, int getline_redirect));
  40. static int iop_close P((IOBUF *iop));
  41. struct redirect *redirect P((NODE *tree, int *errflg));
  42. static void close_one P((void));
  43. static int close_redir P((struct redirect *rp));
  44. #if (!defined(MSDOS)) && (!defined(atarist))
  45. static int wait_any P((int interesting));
  46. #endif
  47. static IOBUF *gawk_popen P((char *cmd, struct redirect *rp));
  48. static int gawk_pclose P((struct redirect *rp));
  49. static int do_pathopen P((char *file));
  50.  
  51. static struct redirect *red_head = NULL;
  52. static IOBUF *curfile = NULL;
  53.  
  54. extern int output_is_tty;
  55. extern NODE *ARGC_node;
  56. extern NODE *ARGV_node;
  57. extern NODE **fields_arr;
  58.  
  59. static IOBUF *
  60. nextfile()
  61. {
  62.     static int i = 1;
  63.     static int files = 0;
  64.     char *arg;
  65.     int fd = INVALID_HANDLE;
  66.     extern char *arg_assign();
  67.  
  68.     if (curfile != NULL && curfile->cnt != EOF)
  69.         return curfile;
  70.     for (; i < (int) (ARGC_node->lnode->numbr); i++) {
  71.         arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
  72.         if (*arg == '\0')
  73.             continue;
  74.         if (!arg_assign(arg)) {
  75.             files++;
  76.             fd = devopen(arg, "r");
  77.             if (fd == INVALID_HANDLE)
  78.                 fatal("cannot open file `%s' for reading (%s)",
  79.                     arg, strerror(errno));
  80.                 /* NOTREACHED */
  81.             /* This is a kludge.  */
  82.             unref(FILENAME_node->var_value);
  83.             FILENAME_node->var_value =
  84.                 make_string(arg, strlen(arg));
  85.             FNR = 0;
  86.             i++;
  87.             break;
  88.         }
  89.     }
  90.     if (files == 0) {
  91.         files++;
  92.         /* no args. -- use stdin */
  93.         /* FILENAME is init'ed to "-" */
  94.         /* FNR is init'ed to 0 */
  95.         fd = 0;
  96.     }
  97.     if (fd == INVALID_HANDLE)
  98.         return NULL;
  99.     return curfile = iop_alloc(fd);
  100. }
  101.  
  102. void
  103. set_FNR()
  104. {
  105.     FNR = (int) FNR_node->var_value->numbr;
  106. }
  107.  
  108. void
  109. set_NR()
  110. {
  111.     NR = (int) NR_node->var_value->numbr;
  112. }
  113.  
  114. /*
  115.  * This reads in a record from the input file
  116.  */
  117. static int
  118. inrec(iop, getline_redirect)
  119. IOBUF *iop;
  120. int getline_redirect;
  121. {
  122.     char *begin;
  123.     register int cnt;
  124.     int retval = 0;
  125.  
  126.     cnt = get_a_record(&begin, iop, *RS);
  127.     if (cnt == EOF) {
  128.         cnt = 0;
  129.         retval = 1;
  130.     } else if (!getline_redirect) {
  131.             NR += 1;
  132.             FNR += 1;
  133.     }
  134.     set_record(begin, cnt, 1);
  135.  
  136.     return retval;
  137. }
  138.  
  139. static int
  140. iop_close(iop)
  141. IOBUF *iop;
  142. {
  143.     int ret;
  144.  
  145.     if (iop == NULL)
  146.         return 0;
  147.     errno = 0;
  148.  
  149.     /* Work around bug in UNICOS popen, but it shouldn't hurt elsewhere */
  150.     if (iop->fd < 3)
  151.         ret = 0;
  152.     else
  153.         ret = close(iop->fd);
  154.     if (ret == -1)
  155.         warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
  156.     free(iop->buf);
  157.     free(iop->secbuf);
  158.     if (iop == curfile)
  159.         curfile = NULL;    /* kludge -- gotta do better */
  160.     free((char *)iop);
  161.     return ret == -1 ? 1 : 0;
  162. }
  163.  
  164. void
  165. do_input()
  166. {
  167.     IOBUF *iop;
  168.     extern int exiting;
  169.  
  170.     while ((iop = nextfile()) != NULL) {
  171.         if (inrec(iop, 0) == 0)
  172.             while (interpret(expression_value) && inrec(iop, 0) == 0)
  173.                 ;
  174.         (void) iop_close(iop);
  175.         iop = NULL;
  176.         if (exiting)
  177.             break;
  178.     }
  179. }
  180.  
  181. /* Redirection for printf and print commands */
  182. struct redirect *
  183. redirect(tree, errflg)
  184. NODE *tree;
  185. int *errflg;
  186. {
  187.     register NODE *tmp;
  188.     register struct redirect *rp;
  189.     register char *str;
  190.     int tflag = 0;
  191.     int outflag = 0;
  192.     char *direction = "to";
  193.     char *mode;
  194.     int fd;
  195.  
  196.     switch (tree->type) {
  197.     case Node_redirect_append:
  198.         tflag = RED_APPEND;
  199.     case Node_redirect_output:
  200.         outflag = (RED_FILE|RED_WRITE);
  201.         tflag |= outflag;
  202.         break;
  203.     case Node_redirect_pipe:
  204.         tflag = (RED_PIPE|RED_WRITE);
  205.         break;
  206.     case Node_redirect_pipein:
  207.         tflag = (RED_PIPE|RED_READ);
  208.         break;
  209.     case Node_redirect_input:
  210.         tflag = (RED_FILE|RED_READ);
  211.         break;
  212.     default:
  213.         fatal ("invalid tree type %d in redirect()", tree->type);
  214.         break;
  215.     }
  216.     tmp = force_string(tree_eval(tree->subnode));
  217.     str = tmp->stptr;
  218.     for (rp = red_head; rp != NULL; rp = rp->next)
  219.         if (strlen(rp->value) == tmp->stlen
  220.             && STREQN(rp->value, str, tmp->stlen)
  221.             && ((rp->flag & ~RED_NOBUF) == tflag
  222.             || (outflag
  223.                 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
  224.             break;
  225.     if (rp == NULL) {
  226.         emalloc(rp, struct redirect *, sizeof(struct redirect),
  227.             "redirect");
  228.         emalloc(str, char *, tmp->stlen+1, "redirect");
  229.         memcpy(str, tmp->stptr, tmp->stlen);
  230.         str[tmp->stlen] = '\0';
  231.         rp->value = str;
  232.         rp->flag = tflag;
  233.         rp->offset = 0;
  234.         rp->fp = NULL;
  235.         rp->iop = NULL;
  236.         rp->pid = 0;    /* unlikely that we're worried about init */
  237.         rp->status = 0;
  238.         /* maintain list in most-recently-used first order */
  239.         if (red_head)
  240.             red_head->prev = rp;
  241.         rp->prev = NULL;
  242.         rp->next = red_head;
  243.         red_head = rp;
  244.     }
  245.     while (rp->fp == NULL && rp->iop == NULL) {
  246.         mode = NULL;
  247.         errno = 0;
  248.         switch (tree->type) {
  249.         case Node_redirect_output:
  250.             mode = "w";
  251.             break;
  252.         case Node_redirect_append:
  253.             mode = "a";
  254.             break;
  255.         case Node_redirect_pipe:
  256.             if ((rp->fp = popen(str, "w")) == NULL)
  257.                 fatal("can't open pipe (\"%s\") for output (%s)",
  258.                     str, strerror(errno));
  259.             rp->flag |= RED_NOBUF;
  260.             break;
  261.         case Node_redirect_pipein:
  262.             direction = "from";
  263.             if (gawk_popen(str, rp) == NULL)
  264.                 fatal("can't open pipe (\"%s\") for input (%s)",
  265.                     str, strerror(errno));
  266.             break;
  267.         case Node_redirect_input:
  268.             direction = "from";
  269.             rp->iop = iop_alloc(devopen(str, "r"));
  270.             break;
  271.         default:
  272.             cant_happen();
  273.         }
  274.         if (mode != NULL) {
  275.             fd = devopen(str, mode);
  276.             if (fd > INVALID_HANDLE) {
  277.                 if (fd == fileno(stdin))
  278.                     rp->fp = stdin;
  279.                 else if (fd == fileno(stdout))
  280.                     rp->fp = stdout;
  281.                 else if (fd == fileno(stderr))
  282.                     rp->fp = stderr;
  283.                 else    
  284.                     rp->fp = fdopen(fd, mode);
  285.                 if (isatty(fd))
  286.                     rp->flag |= RED_NOBUF;
  287.             }
  288.         }
  289.         if (rp->fp == NULL && rp->iop == NULL) {
  290.             /* too many files open -- close one and try again */
  291. #ifdef atarist
  292.             if (errno == EMFILE)
  293. #else
  294.             if (errno == ENFILE || errno == EMFILE)
  295. #endif
  296.                 close_one();
  297.             else {
  298.                 /*
  299.                  * Some other reason for failure.
  300.                  *
  301.                  * On redirection of input from a file,
  302.                  * just return an error, so e.g. getline
  303.                  * can return -1.  For output to file,
  304.                  * complain. The shell will complain on
  305.                  * a bad command to a pipe.
  306.                  */
  307.                 *errflg = 1;
  308.                 if (tree->type == Node_redirect_output
  309.                     || tree->type == Node_redirect_append)
  310.                     fatal("can't redirect %s `%s' (%s)",
  311.                         direction, str, strerror(errno));
  312.                 else
  313.                     return NULL;
  314.             }
  315.         }
  316.     }
  317.     if (rp->offset != 0)    /* this file was previously open */
  318.         if (fseek(rp->fp, rp->offset, 0) == -1)
  319.             fatal("can't seek to %ld on `%s' (%s)",
  320.                 rp->offset, str, strerror(errno));
  321.     free_temp(tmp);
  322.     return rp;
  323. }
  324.  
  325. static void
  326. close_one()
  327. {
  328.     register struct redirect *rp;
  329.     register struct redirect *rplast = NULL;
  330.  
  331.     /* go to end of list first, to pick up least recently used entry */
  332.     for (rp = red_head; rp != NULL; rp = rp->next)
  333.         rplast = rp;
  334.     /* now work back up through the list */
  335.     for (rp = rplast; rp != NULL; rp = rp->prev)
  336.         if (rp->fp && (rp->flag & RED_FILE)) {
  337.             rp->offset = ftell(rp->fp);
  338.             errno = 0;
  339.             if (fclose(rp->fp))
  340.                 warning("close of \"%s\" failed (%s).",
  341.                     rp->value, strerror(errno));
  342.             rp->fp = NULL;
  343.             break;
  344.         }
  345.     if (rp == NULL)
  346.         /* surely this is the only reason ??? */
  347.         fatal("too many pipes or input files open"); 
  348. }
  349.  
  350. NODE *
  351. do_close(tree)
  352. NODE *tree;
  353. {
  354.     NODE *tmp;
  355.     register struct redirect *rp;
  356.  
  357.     tmp = force_string(tree_eval(tree->subnode));
  358.     for (rp = red_head; rp != NULL; rp = rp->next) {
  359.         if (strlen(rp->value) == tmp->stlen
  360.             && STREQN(rp->value, tmp->stptr, tmp->stlen))
  361.             break;
  362.     }
  363.     free_temp(tmp);
  364.     if (rp == NULL) /* no match */
  365.         return tmp_number((AWKNUM) 0.0);
  366.     fflush(stdout);    /* synchronize regular output */
  367.     tmp = tmp_number((AWKNUM)close_redir(rp));
  368.     rp = NULL;
  369.     return tmp;
  370. }
  371.  
  372. static int
  373. close_redir(rp)
  374. register struct redirect *rp;
  375. {
  376.     int status = 0;
  377.  
  378.     if (rp == NULL)
  379.         return 0;
  380.     errno = 0;
  381.     if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE))
  382.         status = pclose(rp->fp);
  383.     else if (rp->fp)
  384.         status = fclose(rp->fp);
  385.     else if (rp->iop) {
  386.         if (rp->flag & RED_PIPE)
  387.             status = gawk_pclose(rp);
  388.         else {
  389.             status = iop_close(rp->iop);
  390.             rp->iop = NULL;
  391.         }
  392.     }
  393.     /* SVR4 awk checks and warns about status of close */
  394.     if (status)
  395.         warning("failure status (%d) on %s close of \"%s\" (%s).",
  396.             status,
  397.             (rp->flag & RED_PIPE) ? "pipe" :
  398.             "file", rp->value, strerror(errno));
  399.     if (rp->next)
  400.         rp->next->prev = rp->prev;
  401.     if (rp->prev)
  402.         rp->prev->next = rp->next;
  403.     else
  404.         red_head = rp->next;
  405.     free(rp->value);
  406.     free((char *)rp);
  407.     return status;
  408. }
  409.  
  410. int
  411. flush_io ()
  412. {
  413.     register struct redirect *rp;
  414.     int status = 0;
  415.  
  416.     errno = 0;
  417.     if (fflush(stdout)) {
  418.         warning("error writing standard output (%s).", strerror(errno));
  419.         status++;
  420.     }
  421.     errno = 0;
  422.     if (fflush(stderr)) {
  423.         warning("error writing standard error (%s).", strerror(errno));
  424.         status++;
  425.     }
  426.     for (rp = red_head; rp != NULL; rp = rp->next)
  427.         /* flush both files and pipes, what the heck */
  428.         if ((rp->flag & RED_WRITE) && rp->fp != NULL) {
  429.             errno = 0;
  430.             if (fflush(rp->fp)) {
  431.                 warning("%s flush of \"%s\" failed (%s).",
  432.                     (rp->flag  & RED_PIPE) ? "pipe" :
  433.                     "file", rp->value, strerror(errno));
  434.                 status++;
  435.             }
  436.         }
  437.     return status;
  438. }
  439.  
  440. int
  441. close_io ()
  442. {
  443.     register struct redirect *rp;
  444.     register struct redirect *next;
  445.     int status = 0;
  446.  
  447.     for (rp = red_head; rp != NULL; rp = next) {
  448.         next = rp->next;
  449.         if (close_redir(rp))
  450.             status++;
  451.         rp = NULL;
  452.     }
  453.     return status;
  454. }
  455.  
  456. /* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
  457.  
  458. int
  459. devopen (name, mode)
  460. char *name, *mode;
  461. {
  462.     int openfd = INVALID_HANDLE;
  463.     FILE *fdopen ();
  464.     char *cp, *ptr;
  465.     int flag = 0;
  466.     struct stat buf;
  467.  
  468.     switch(mode[0]) {
  469.     case 'r':
  470.         flag = O_RDONLY;
  471.         break;
  472.  
  473.     case 'w':
  474.         flag = O_WRONLY|O_CREAT|O_TRUNC;
  475.         break;
  476.  
  477.     case 'a':
  478.         flag = O_WRONLY|O_APPEND|O_CREAT;
  479.         break;
  480.     default:
  481.         cant_happen();
  482.     }
  483.  
  484. #ifdef VMS
  485.     if ((openfd = vms_devopen(name)) >= 0)
  486.         return openfd;
  487. # define strcmp  strcasecmp    /* VMS filenames are not case sensitive; */
  488. # define strncmp strncasecmp    /*  strncmp() is used by STREQN() below. */
  489. #endif /*VMS*/
  490.  
  491.     if ((openfd = open(name, flag, 0666)) > INVALID_HANDLE)
  492.         return openfd;
  493.  
  494.     if (STREQ(name, "-"))
  495.         openfd = fileno(stdin);
  496.     else if (STREQN(name, "/dev/", 5) && stat(name, &buf) == -1) {
  497.         cp = name + 5;
  498.         
  499.         /* XXX - first three tests ignore mode */
  500.         if (STREQ(cp, "stdin") && (flag & O_RDONLY))
  501.             openfd = fileno(stdin);
  502.         else if (STREQ(cp, "stdout") && (flag & O_WRONLY))
  503.             openfd = fileno(stdout);
  504.         else if (STREQ(cp, "stderr") && (flag & O_WRONLY))
  505.             openfd = fileno(stderr);
  506.         else if (STREQN(cp, "fd/", 3)) {
  507.             cp += 3;
  508.             openfd = strtol(cp, &ptr, 10);
  509.             if (openfd <= INVALID_HANDLE || ptr == cp)
  510.                 openfd = INVALID_HANDLE;
  511. #ifdef VMS
  512.         } else if (STREQ(cp, "null")) {
  513.             name = "NL:";    /* "/dev/null" => "NL:" */
  514.         } else if (STREQ(cp, "tty")) {
  515.             name = "TT:";    /* "/dev/tty" => "TT:" */
  516. # undef strcmp
  517. # undef strncmp
  518. #endif /*VMS*/
  519.         }
  520.     }
  521.  
  522.     if (openfd != INVALID_HANDLE)
  523.         return openfd;
  524.     else
  525.         return open(name, flag, 0666);
  526. }
  527.  
  528. #if defined(MSDOS) || defined(atarist)
  529. #define PIPES_SIMULATED
  530. #endif
  531.  
  532. #ifndef PIPES_SIMULATED
  533.     /* real pipes */
  534. static int
  535. wait_any(interesting)
  536. int interesting;    /* pid of interest, if any */
  537. {
  538.     SIGTYPE (*hstat)(), (*istat)(), (*qstat)();
  539.     int pid;
  540.     int status = 0;
  541.     struct redirect *redp;
  542.     extern int errno;
  543.  
  544.     hstat = signal(SIGHUP, SIG_IGN);
  545.     istat = signal(SIGINT, SIG_IGN);
  546.     qstat = signal(SIGQUIT, SIG_IGN);
  547.     for (;;) {
  548.         pid = wait(&status);
  549.         if (interesting && pid == interesting) {
  550.             break;
  551.         } else if (pid != -1) {
  552.             for (redp = red_head; redp != NULL; redp = redp->next)
  553.                 if (pid == redp->pid) {
  554.                     redp->pid = -1;
  555.                     redp->status = status;
  556.                     if (redp->fp) {
  557.                         pclose(redp->fp);
  558.                         redp->fp = 0;
  559.                     }
  560.                     if (redp->iop) {
  561.                         (void) iop_close(redp->iop);
  562.                         redp->iop = 0;
  563.                     }
  564.                     break;
  565.                 }
  566.         }
  567.         if (pid == -1 && errno == ECHILD)
  568.             break;
  569.     }
  570.     signal(SIGHUP, hstat);
  571.     signal(SIGINT, istat);
  572.     signal(SIGQUIT, qstat);
  573.     return(status);
  574. }
  575.  
  576. static IOBUF *
  577. gawk_popen(cmd, rp)
  578. char *cmd;
  579. struct redirect *rp;
  580. {
  581.     int p[2];
  582.     register int pid;
  583.  
  584.     (void) wait_any(0);    /* wait for outstanding processes */
  585.     if (pipe(p) < 0)
  586.         fatal("cannot open pipe \"%s\" (%s)", cmd, strerror(errno));
  587.     if ((pid = fork()) == 0) {
  588.         if (close(1) == -1)
  589.             fatal("close of stdout in child failed (%s)",
  590.                 strerror(errno));
  591.         if (dup(p[1]) != 1)
  592.             fatal("dup of pipe failed (%s)", strerror(errno));
  593.         if (close(p[0]) == -1 || close(p[1]) == -1)
  594.             fatal("close of pipe failed (%s)", strerror(errno));
  595.         execl("/bin/sh", "sh", "-c", cmd, 0);
  596.         _exit(127);
  597.     }
  598.     if (pid == -1)
  599.         fatal("cannot fork for \"%s\" (%s)", cmd, strerror(errno));
  600.     rp->pid = pid;
  601.     if (close(p[1]) == -1)
  602.         fatal("close of pipe failed (%s)", strerror(errno));
  603.     return (rp->iop = iop_alloc(p[0]));
  604. }
  605.  
  606. static int
  607. gawk_pclose(rp)
  608. struct redirect *rp;
  609. {
  610.     (void) iop_close(rp->iop);
  611.     rp->iop = NULL;
  612.  
  613.     /* process previously found, return stored status */
  614.     if (rp->pid == -1)
  615.         return (rp->status >> 8) & 0xFF;
  616.     rp->status = wait_any(rp->pid);
  617.     rp->pid = -1;
  618.     return (rp->status >> 8) & 0xFF;
  619. }
  620.  
  621. #else    /* PIPES_SUMULATED */
  622.     /* use temporary file rather than pipe */
  623.  
  624. #ifdef VMS
  625. static IOBUF *
  626. gawk_popen(cmd, rp)
  627. char *cmd;
  628. struct redirect *rp;
  629. {
  630.     FILE *current;
  631.  
  632.     if ((current = popen(cmd, "r")) == NULL)
  633.         return NULL;
  634.     return (rp->iop = iop_alloc(fileno(current)));
  635. }
  636.  
  637. static int
  638. gawk_pclose(rp)
  639. struct redirect *rp;
  640. {
  641.     int rval, aval, fd = rp->iop->fd;
  642.     FILE *kludge = fdopen(fd, "r"); /* pclose needs FILE* w/ right fileno */
  643.  
  644.     rp->iop->fd = dup(fd);      /* kludge to allow close() + pclose() */
  645.     rval = iop_close(rp->iop);
  646.     aval = pclose(kludge);
  647.     return (rval < 0 ? rval : aval);
  648. }
  649. #else    /* VMS */
  650.  
  651. static
  652. struct {
  653.     char *command;
  654.     char *name;
  655. } pipes[_NFILE];
  656.  
  657. static IOBUF *
  658. gawk_popen(cmd, rp)
  659. char *cmd;
  660. struct redirect *rp;
  661. {
  662.     extern char *strdup(const char *);
  663.     int current;
  664.     char *name;
  665.     static char cmdbuf[256];
  666.  
  667.     /* get a name to use.  */
  668.     if ((name = tempnam(".", "pip")) == NULL)
  669.         return NULL;
  670.     sprintf(cmdbuf,"%s > %s", cmd, name);
  671.     system(cmdbuf);
  672.     if ((current = open(name,O_RDONLY)) == INVALID_HANDLE)
  673.         return NULL;
  674.     pipes[current].name = name;
  675.     pipes[current].command = strdup(cmd);
  676.     return (rp->iop = iop_alloc(current));
  677. }
  678.  
  679. static int
  680. gawk_pclose(rp)
  681. struct redirect *rp;
  682. {
  683.     int cur = rp->iop->fd;
  684.     int rval;
  685.  
  686.     rval = iop_close(rp->iop);
  687.     rp->iop = NULL;
  688.  
  689.     /* check for an open file  */
  690.     if (pipes[cur].name == NULL)
  691.         return -1;
  692.     unlink(pipes[cur].name);
  693.     free(pipes[cur].name);
  694.     pipes[cur].name = NULL;
  695.     free(pipes[cur].command);
  696.     return rval;
  697. }
  698. #endif    /* VMS */
  699.  
  700. #endif    /* PIPES_SUMULATED */
  701.  
  702. NODE *
  703. do_getline(tree)
  704. NODE *tree;
  705. {
  706.     struct redirect *rp = NULL;
  707.     IOBUF *iop;
  708.     int cnt;
  709.     NODE **lhs;
  710.     int redir_error = 0;
  711.     int getline_redirect = 0;
  712.  
  713.     if (tree->rnode == NULL) {     /* no redirection */
  714.         iop = nextfile();
  715.         if (iop == NULL)        /* end of input */
  716.             return tmp_number((AWKNUM) 0.0);
  717.     } else {
  718.         rp = redirect(tree->rnode, &redir_error);
  719.         if (rp == NULL && redir_error)    /* failed redirect */
  720.             return tmp_number((AWKNUM) -1.0);
  721.         iop = rp->iop;
  722.         getline_redirect++;
  723.     }
  724.     if (tree->lnode == NULL) {    /* no optional var. -- read in $0 */
  725.         if (inrec(iop, getline_redirect) != 0)
  726.             return tmp_number((AWKNUM) 0.0);
  727.     } else {            /* read in a named variable */
  728.         char *s = NULL;
  729.         Func_ptr after_assign = NULL;
  730.  
  731.         lhs = get_lhs(tree->lnode, &after_assign);
  732.         cnt = get_a_record(&s, iop, *RS);
  733.         if (!getline_redirect) {
  734.             NR += 1;
  735.             FNR += 1;
  736.         }
  737.         if (cnt == EOF) {
  738.             if (rp) {
  739.                 (void) iop_close(iop);
  740.                 rp->iop = NULL;
  741.             }
  742.             return tmp_number((AWKNUM) 0.0);
  743.         }
  744.         unref(*lhs);
  745.         *lhs = make_string(s, strlen(s));
  746.         /* we may have to regenerate $0 here! */
  747.         if (after_assign)
  748.             (*after_assign)();
  749.     }
  750.     return tmp_number((AWKNUM) 1.0);
  751. }
  752.  
  753. int
  754. pathopen (file)
  755. char *file;
  756. {
  757.     int fd = do_pathopen(file);
  758.  
  759. #ifdef DEFAULT_FILETYPE
  760.     if (!strict && fd <= INVALID_HANDLE) {
  761.         char *file_awk;
  762.         int save = errno;
  763. #ifdef VMS
  764.         int vms_save = vaxc$errno;
  765. #endif
  766.  
  767.         /* append ".awk" and try again */
  768.         emalloc(file_awk, char *, strlen(file) +
  769.             sizeof(DEFAULT_FILETYPE) + 1, "pathopen");
  770.         strcat(strcpy(file_awk, file), DEFAULT_FILETYPE);
  771.         fd = do_pathopen(file_awk);
  772.         free(file_awk);
  773.         if (fd <= INVALID_HANDLE) {
  774.             errno = save;
  775. #ifdef VMS
  776.             vaxc$errno = vms_save;
  777. #endif
  778.         }
  779.     }
  780. #endif    /*DEFAULT_FILETYPE*/
  781.  
  782.     return fd;
  783. }
  784.  
  785. static int
  786. do_pathopen (file)
  787. char *file;
  788. {
  789.     static char *savepath = DEFPATH;    /* defined in config.h */
  790.     static int first = 1;
  791.     char *awkpath, *cp;
  792.     char trypath[BUFSIZ];
  793.     int fd;
  794.  
  795.     if (STREQ(file, "-"))
  796.         return (0);
  797.  
  798.     if (strict)
  799.         return (open (file, 0));
  800.  
  801.     if (first) {
  802.         first = 0;
  803.         if ((awkpath = getenv ("AWKPATH")) != NULL && *awkpath)
  804.             savepath = awkpath;    /* used for restarting */
  805.     }
  806.     awkpath = savepath;
  807.  
  808.     /* some kind of path name, no search */
  809. #ifdef VMS    /* (strchr not equal implies either or both not NULL) */
  810.     if (strchr(file, ':') != strchr(file, ']')
  811.      || strchr(file, '>') != strchr(file, '/'))
  812. #else /*!VMS*/
  813. #ifdef MSDOS
  814.     if (strchr(file, '/') != strchr(file, '\\')
  815.      || strchr(file, ':') != NULL)
  816. #else
  817.     if (strchr(file, '/') != NULL)
  818. #endif    /*MSDOS*/
  819. #endif    /*VMS*/
  820.         return (devopen (file, "r"));
  821.  
  822.     do {
  823.         trypath[0] = '\0';
  824.         /* this should take into account limits on size of trypath */
  825.         for (cp = trypath; *awkpath && *awkpath != ENVSEP; )
  826.             *cp++ = *awkpath++;
  827.  
  828.         if (cp != trypath) {    /* nun-null element in path */
  829.             *cp++ = '/';
  830.             strcpy (cp, file);
  831.         } else
  832.             strcpy (trypath, file);
  833.         if ((fd = devopen (trypath, "r")) >= 0)
  834.             return (fd);
  835.  
  836.         /* no luck, keep going */
  837.         if(*awkpath == ENVSEP && awkpath[1] != '\0')
  838.             awkpath++;    /* skip colon */
  839.     } while (*awkpath);
  840.     /*
  841.      * You might have one of the awk
  842.      * paths defined, WITHOUT the current working directory in it.
  843.      * Therefore try to open the file in the current directory.
  844.      */
  845.     return (devopen(file, "r"));
  846. }
  847.