static char *
read_comsub (fd, quoted, rflag)
     int fd, quoted;
     int *rflag;
{
  char *istring, buf[128], *bufp, *s;
  int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
  ssize_t bufn;
  int nullbyte;

  istring = (char *)NULL;
  istring_index = istring_size = bufn = tflag = 0;

  for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
    skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;

  nullbyte = 0;

  /* Read the output of the command through the pipe.  This may need to be
     changed to understand multibyte characters in the future. */
  while (1)
    {
      if (fd < 0)
	break;
      if (--bufn <= 0)
	{
	  bufn = zread (fd, buf, sizeof (buf));
	  if (bufn <= 0) 
	    break;
	  bufp = buf;
	}
      c = *bufp++;

      if (c == 0)
	{
#if 1
	  if (nullbyte == 0)
	    {
	      internal_warning ("%s", _("command substitution: ignored null byte in input"));
	      nullbyte = 1;
	    }
#endif
	  continue;
	}

      /* Add the character to ISTRING, possibly after resizing it. */
      RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);

      /* This is essentially quote_string inline */
      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
	istring[istring_index++] = CTLESC;
      /* Escape CTLESC and CTLNUL in the output to protect those characters
	 from the rest of the word expansions (word splitting and globbing.)
	 This is essentially quote_escapes inline. */
      else if (skip_ctlesc == 0 && c == CTLESC)
	{
	  tflag |= W_HASCTLESC;
	  istring[istring_index++] = CTLESC;
	}
      else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
	istring[istring_index++] = CTLESC;

      istring[istring_index++] = c;

#if 0
#if defined (__CYGWIN__)
      if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
	{
	  istring_index--;
	  istring[istring_index - 1] = '\n';
	}
#endif
#endif
    }

  if (istring)
    istring[istring_index] = '\0';

  /* If we read no output, just return now and save ourselves some
     trouble. */
  if (istring_index == 0)
    {
      FREE (istring);
      if (rflag)
	*rflag = tflag;
      return (char *)NULL;
    }

  /* Strip trailing newlines from the output of the command. */
  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
    {
      while (istring_index > 0)
	{
	  if (istring[istring_index - 1] == '\n')
	    {
	      --istring_index;

	      /* If the newline was quoted, remove the quoting char. */
	      if (istring[istring_index - 1] == CTLESC)
		--istring_index;
	    }
	  else
	    break;
	}
      istring[istring_index] = '\0';
    }
  else
    strip_trailing (istring, istring_index - 1, 1);

  if (rflag)
    *rflag = tflag;
  return istring;
static char *
read_comsub (fd, quoted, rflag)
     int fd, quoted;
     int *rflag;
{
  char *istring, buf[128], *bufp, *s;
  int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
  ssize_t bufn;
  int nullbyte;

  istring = (char *)NULL;
  istring_index = istring_size = bufn = tflag = 0;

  for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
    skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;

  nullbyte = 0;

   
  while (1)
    {
      if (fd < 0)
	break;
      if (--bufn <= 0)
	{
	  bufn = zread (fd, buf, sizeof (buf));
	  if (bufn <= 0) 
	    break;
	  bufp = buf;
	}
      c = *bufp++;

      if (c == 0)
	{
#if 1
	  if (nullbyte == 0)
	    {
	      internal_warning ("%s", _("command substitution: ignored null byte in input"));
	      nullbyte = 1;
	    }
#endif
	  continue;
	}

       
      RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);

       
      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))  )
	istring[istring_index++] = CTLESC;
       
      else if (skip_ctlesc == 0 && c == CTLESC)
	{
	  tflag |= W_HASCTLESC;
	  istring[istring_index++] = CTLESC;
	}
      else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
	istring[istring_index++] = CTLESC;

      istring[istring_index++] = c;

#if 0
#if defined (__CYGWIN__)
      if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
	{
	  istring_index--;
	  istring[istring_index - 1] = '\n';
	}
#endif
#endif
    }

  if (istring)
    istring[istring_index] = '\0';

   
  if (istring_index == 0)
    {
      FREE (istring);
      if (rflag)
	*rflag = tflag;
      return (char *)NULL;
    }

   
  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
    {
      while (istring_index > 0)
	{
	  if (istring[istring_index - 1] == '\n')
	    {
	      --istring_index;

	       
	      if (istring[istring_index - 1] == CTLESC)
		--istring_index;
	    }
	  else
	    break;
	}
      istring[istring_index] = '\0';
    }
  else
    strip_trailing (istring, istring_index - 1, 1);

  if (rflag)
    *rflag = tflag;
  return istring;