diff -rup src/gdb/Makefile.in dst/gdb/Makefile.in --- src/gdb/Makefile.in 2011-07-27 23:55:26.000000000 +0530 +++ dst/gdb/Makefile.in 2011-07-29 16:12:32.578048797 +0530 @@ -713,7 +713,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr objc-exp.y objc-lang.c \ objfiles.c osabi.c observer.c osdata.c \ opencl-lang.c \ - p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \ + p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c pipe.c printcmd.c \ proc-service.list progspace.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ @@ -870,7 +870,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $ mi-common.o \ event-loop.o event-top.o inf-loop.o completer.o \ gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o \ - memattr.o mem-break.o target.o parse.o language.o buildsym.o \ + memattr.o mem-break.o target.o parse.o pipe.o language.o buildsym.o \ findcmd.o \ std-regs.o \ signals.o \ diff -rup src/gdb/pipe.c dst/gdb/pipe.c --- src/gdb/pipe.c 2011-07-29 15:15:26.078048517 +0530 +++ dst/gdb/pipe.c 2011-08-09 15:53:48.462145884 +0530 @@ -0,0 +1,210 @@ +/* Everything about pipe, for GDB. + + Copyright (C) 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include +#include "gdb_string.h" +#include "ui-file.h" +#include "ui-out.h" +#include "cli/cli-utils.h" +#include "gdbcmd.h" +#include "libiberty.h" + +/* Structure to encapsulate all entities associated with pipe. */ + +struct pipe_obj +{ + /* The delimiter to separate out gdb-command and shell-command. This can be + any arbitrary string without containing any whitespace. */ + char *dlim; + + /* The gdb-command. */ + char *gdb_cmd; + + /* The shell-command. */ + char *shell_cmd; + + /* The gdb-side stream pointer to the pipe. */ + FILE *handle; + + /* The pex object used to create pipeline between gdb and shell. */ + struct pex_obj *pex; +}; + +/* Construct a pipe object by parsing argument to the pipe command. */ + +static struct pipe_obj * +construct_pipe (char *p) +{ + char *t; + struct pipe_obj *pipe = NULL; + struct cleanup *cleanup; + + if (p == NULL) + error (_("No argument is specified")); + + pipe = XCNEW (struct pipe_obj); + cleanup = make_cleanup (xfree, pipe); + + pipe->dlim = p; + + t = skip_to_space (p); + p = skip_spaces (t); + + if (*p == '\0') + error (_("No gdb-command is specified")); + + *t = '\0'; + pipe->gdb_cmd = p; + + for (;;) + { + t = skip_to_space (p); + + if (*t == '\0') + error (_("No shell-command is specified")); + + /* Check whether the token separated by whitespace matches with + delimiter. */ + if (memcmp (p, pipe->dlim, (t - p)) == 0) + { + *p = '\0'; + pipe->shell_cmd = skip_spaces (t); + break; + } + + p = skip_spaces (t); + } + + discard_cleanups (cleanup); + return pipe; +} + +/* Run execute_command for P and FROM_TTY. Write output to the pipe, do not + display it to the screen. */ + +static void +execute_command_to_pipe (struct pipe_obj *pipe, int from_tty) +{ + char **argv; + struct cleanup *cleanup; + struct ui_file *fp; + + argv = gdb_buildargv (pipe->shell_cmd); + cleanup = make_cleanup_freeargv (argv); + + pipe->pex = pex_init (PEX_USE_PIPES, argv[0], NULL); + + if (pipe->pex == NULL) + do_cleanups (cleanup); + + pipe->handle = pex_input_pipe (pipe->pex, 0); + + if (pipe->handle == NULL) + error (_("Failed to create pipe")); + + { + int status; + const char *err + = pex_run (pipe->pex, + PEX_SEARCH | PEX_LAST | PEX_STDERR_TO_STDOUT, + argv[0], argv, + NULL, NULL, + &status); + if (err != NULL) + error (_("Failed to execute %s"), argv[0]); + + do_cleanups (cleanup); + } + + /* GDB_STDOUT should be better already restored during these + restoration callbacks. */ + cleanup = set_batch_flag_and_make_cleanup_restore_page_info (); + fp = stdio_fileopen (pipe->handle); + make_cleanup_ui_file_delete (fp); + make_cleanup_restore_ui_file (&gdb_stdout); + make_cleanup_restore_ui_file (&gdb_stderr); + make_cleanup_restore_ui_file (&gdb_stdlog); + make_cleanup_restore_ui_file (&gdb_stdtarg); + make_cleanup_restore_ui_file (&gdb_stdtargerr); + + if (ui_out_redirect (uiout, fp) < 0) + warning (_("Current output protocol does not support redirection")); + else + make_cleanup_ui_out_redirect_pop (uiout); + + gdb_stdout = fp; + gdb_stderr = fp; + gdb_stdlog = fp; + gdb_stdtarg = fp; + gdb_stdtargerr = fp; + execute_command (pipe->gdb_cmd, from_tty); + do_cleanups (cleanup); +} + +/* Destruct pipe object. */ + +static void +destruct_pipe (void *arg) +{ + struct pipe_obj *pipe = (struct pipe_obj *)arg; + + if (pipe->handle != NULL) + fclose (pipe->handle); + + if (pipe->pex != NULL) + { + int status; + + /* Wait till the process in the other side of the pipe completes its + job before closing its file descryptors. */ + pex_get_status (pipe->pex, 1, &status); + pex_free (pipe->pex); + } + + xfree (pipe); +} + +/* Execute the pipe command. */ + +static void +pipe_command (char *arg, int from_tty) +{ + struct pipe_obj *pipe = construct_pipe (arg); + + if (pipe != NULL) + { + struct cleanup *cleanup = make_cleanup (destruct_pipe, pipe); + + execute_command_to_pipe (pipe, from_tty); + do_cleanups (cleanup); + } +} + +/* Module initialization. */ + +void +_initialize_pipe (void) +{ + add_cmd ("pipe", no_class, pipe_command, _("\ +Create pipe to pass gdb-command output to the shell for processing.\n\ +Arguments are a delimiter, followed by a gdb-command, then the same delimiter \ +again and finally a shell-command."), + &cmdlist); +}