home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / MPW / gawk 2.11.1r3 / Sources / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-02  |  18.4 KB  |  885 lines  |  [TEXT/MPS ]

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