Beispiel #1
0
/* Create a bi-directional pipe to a test child, and validate that the
   child program returns the expected output.
   PROG is the program to run in the child process.
   STDERR_CLOSED is true if we have already closed fd 2.  */
static void
test_pipe (const char *prog, bool stderr_closed)
{
  int fd[2];
  char *argv[3];
  pid_t pid;
  char buffer[2] = { 'a', 't' };

  /* Set up child.  */
  argv[0] = (char *) prog;
  argv[1] = (char *) (stderr_closed ? "1" : "0");
  argv[2] = NULL;
  pid = create_pipe_bidi (prog, prog, argv, false, true, true, fd);
  ASSERT (0 <= pid);
  ASSERT (STDERR_FILENO < fd[0]);
  ASSERT (STDERR_FILENO < fd[1]);

  /* Push child's input.  */
  ASSERT (write (fd[1], buffer, 1) == 1);
  ASSERT (close (fd[1]) == 0);

  /* Get child's output.  */
  ASSERT (read (fd[0], buffer, 2) == 1);

  /* Wait for child.  */
  ASSERT (wait_subprocess (pid, prog, true, false, true, true, NULL) == 0);
  ASSERT (close (fd[0]) == 0);

  /* Check the result.  */
  ASSERT (buffer[0] == 'b');
  ASSERT (buffer[1] == 't');
}
Beispiel #2
0
struct pipe_filter_gi *
pipe_filter_gi_create (const char *progname,
                       const char *prog_path, const char **prog_argv,
                       bool null_stderr, bool exit_on_error,
                       prepare_read_fn prepare_read,
                       done_read_fn done_read,
                       void *private_data)
{
  struct pipe_filter_gi *filter;

  filter =
    (struct pipe_filter_gi *) xmalloc (sizeof (struct pipe_filter_gi));

  /* Open a bidirectional pipe to a subprocess.  */
  filter->child = create_pipe_bidi (progname, prog_path, (char **) prog_argv,
                                    null_stderr, true, exit_on_error,
                                    filter->fd);
  filter->progname = progname;
  filter->null_stderr = null_stderr;
  filter->exit_on_error = exit_on_error;
  filter->prepare_read = prepare_read;
  filter->done_read = done_read;
  filter->private_data = private_data;
  filter->exited = false;
  filter->exitstatus = 0;
  filter->writer_terminated = false;
  filter->writer_errno = 0;
  filter->reader_terminated = false;
  filter->reader_errno = 0;

  if (filter->child == -1)
    {
      /* Child process could not be created.
         Arrange for filter_retcode (filter) to be the current errno.  */
      filter->writer_errno = errno;
      filter->writer_terminated = true;
      filter->exited = true;
    }
  else if (filter_init (filter) < 0)
    filter_terminate (filter);

  return filter;
}
Beispiel #3
0
static void
output_skeleton (void)
{
  int filter_fd[2];
  pid_t pid;

  /* Compute the names of the package data dir and skeleton files.  */
  char const *m4 = (m4 = getenv ("M4")) ? m4 : M4;
  char const *datadir = pkgdatadir ();
  char *m4sugar = xconcatenated_filename (datadir, "m4sugar/m4sugar.m4", NULL);
  char *m4bison = xconcatenated_filename (datadir, "bison.m4", NULL);
  char *skel = (IS_PATH_WITH_DIR (skeleton)
                ? xstrdup (skeleton)
                : xconcatenated_filename (datadir, skeleton, NULL));

  /* Test whether m4sugar.m4 is readable, to check for proper
     installation.  A faulty installation can cause deadlock, so a
     cheap sanity check is worthwhile.  */
  xfclose (xfopen (m4sugar, "r"));

  /* Create an m4 subprocess connected to us via two pipes.  */

  if (trace_flag & trace_tools)
    fprintf (stderr, "running: %s %s - %s %s\n",
             m4, m4sugar, m4bison, skel);

  /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a
     position-dependent manner.  Keep it as the first argument so that all
     files are traced.

     See the thread starting at
     <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
     for details.  */
  {
    char const *argv[10];
    int i = 0;
    argv[i++] = m4;

    /* When POSIXLY_CORRECT is set, GNU M4 1.6 and later disable GNU
       extensions, which Bison's skeletons depend on.  With older M4,
       it has no effect.  M4 1.4.12 added a -g/--gnu command-line
       option to make it explicit that a program wants GNU M4
       extensions even when POSIXLY_CORRECT is set.

       See the thread starting at
       <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
       for details.  */
    if (*M4_GNU_OPTION)
      argv[i++] = M4_GNU_OPTION;

    argv[i++] = "-I";
    argv[i++] = datadir;
    if (trace_flag & trace_m4)
      argv[i++] = "-dV";
    argv[i++] = m4sugar;
    argv[i++] = "-";
    argv[i++] = m4bison;
    argv[i++] = skel;
    argv[i++] = NULL;
    aver (i <= ARRAY_CARDINALITY (argv));

    /* The ugly cast is because gnulib gets the const-ness wrong.  */
    pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
                            true, filter_fd);
  }

  free (m4sugar);
  free (m4bison);
  free (skel);

  if (trace_flag & trace_muscles)
    muscles_output (stderr);
  {
    FILE *out = xfdopen (filter_fd[1], "w");
    muscles_output (out);
    xfclose (out);
  }

  /* Read and process m4's output.  */
  timevar_push (TV_M4);
  {
    FILE *in = xfdopen (filter_fd[0], "r");
    scan_skel (in);
    /* scan_skel should have read all of M4's output.  Otherwise, when we
       close the pipe, we risk letting M4 report a broken-pipe to the
       Bison user.  */
    aver (feof (in));
    xfclose (in);
  }
  wait_subprocess (pid, "m4", false, false, true, true, NULL);
  timevar_pop (TV_M4);
}