This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
On Mon, Aug 15, 2011 at 1:25 AM, Jan Kratochvil <jan.kratochvil@redhat.com> wrote: > On Sun, 14 Aug 2011 21:41:57 +0200, Eli Zaretskii wrote: >> > Abhijit Halder has suggested the suggested >> > ? ? const char *argv[] = { "sh", "-c", "cat >/dev/null", NULL }; >> > ? ? pex_run (pipe->pex, PEX_LAST, "/bin/sh", argv, NULL, NULL, &status); >> > works on UNIX but it will probably not work on MinGW as there is no "/bin/sh", >> > is it? >> >> The file name of the shell, the "-c" switch, and the null device >> should all be system-dependent. ?For MinGW, they should be, >> respectively, "cmd.exe", "/c", and "nul". > > "cat >/dev/null" itself is user-entered command so that part is OK to be > non-cross-platform (therefore also "nul" is not valid). > > OK, "cmd.exe" with "/c" seems easy enough. > > >> > The current implementation: >> > ? ? const char *argv[] = { "cat", ">/dev/null", NULL }; >> > ? ? pex_run (pipe->pex, PEX_SEARCH | PEX_LAST, "cat", argv, NULL, NULL, &status); >> > produces that - therefore not working on UNIX: >> > ? ? cat: >/dev/null: No such file or directory >> >> How hard is it to parse the redirection characters? > > Very, >, >>, &>, >&, &>>, x>&y, x>&y-, x<>y, many more. > > > Thanks, > Jan > Corrected the pattern matching code and added code to take care MinGW. Working on testcase and doc part.
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-08-14 07:31:15.802233004 +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/NEWS dst/gdb/NEWS --- src/gdb/NEWS 2011-08-14 07:27:51.582233000 +0530 +++ dst/gdb/NEWS 2011-08-14 07:50:38.562234498 +0530 @@ -64,6 +64,9 @@ * New commands "info macros", and "info definitions" have been added. +* New command "pipe" has been added to make GDB command output available to the + shell for processing. + * Changed commands watch EXPRESSION mask MASK_VALUE 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-16 14:05:56.771665999 +0530 @@ -0,0 +1,227 @@ +/* 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 <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include <ctype.h> +#include "gdb_string.h" +#include "ui-file.h" +#include "ui-out.h" +#include "cli/cli-utils.h" +#include "gdbcmd.h" +#include "libiberty.h" +#include "exceptions.h" + +#if defined(__MINGW32__) +#define SHELL "cmd.exe" +#define OPTION_TO_SHELL "/c" +#else +#define SHELL "/bin/sh" +#define OPTION_TO_SHELL "-c" +#endif + +/* 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; +}; + +/* Destruct pipe object referenced by ARG. */ + +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 on the other side of the pipe completes its + job before closing its file descriptors. */ + pex_get_status (pipe->pex, 1, &status); + + if (!WIFEXITED (status)) + warning (_("Execution of shell-command `%s' may not be completed"), + pipe->shell_cmd); + + pex_free (pipe->pex); + } + + xfree (pipe->dlim); + xfree (pipe); +} + +/* Construct a pipe object by parsing argument ARG to the pipe command. */ + +static struct pipe_obj * +construct_pipe (char *arg) +{ + char *p, *t; + struct pipe_obj *pipe = NULL; + struct cleanup *cleanup; + + if (arg == NULL) + error (_("No argument is specified")); + + pipe = XCNEW (struct pipe_obj); + cleanup = make_cleanup (destruct_pipe, pipe); + + p = xstrdup (arg); + pipe->dlim = p; + + if (*pipe->dlim == '-') + error (_("Delimiter pattern should not start with '-'")); + + 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 + && 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 PIPE 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[4]; + struct cleanup *cleanup; + struct ui_file *fp; + int status; + const char *errmsg; + volatile struct gdb_exception exception; + + argv[0] = SHELL; + argv[1] = OPTION_TO_SHELL; + argv[2] = pipe->shell_cmd; + argv[3] = NULL; + + pipe->pex = pex_init (PEX_USE_PIPES, argv[0], NULL); + pipe->handle = pex_input_pipe (pipe->pex, 0); + + if (pipe->handle == NULL) + error (_("Failed to create pipe")); + + errmsg = pex_run (pipe->pex, PEX_LAST, argv[0], argv, NULL, NULL, &status); + + if (errmsg != NULL) + error (_("Failed to execute shell-command `%s' on pipe: %s"), + pipe->shell_cmd, errmsg); + + /* 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 (current_uiout, fp) < 0) + warning (_("Current output protocol does not support redirection")); + else + make_cleanup_ui_out_redirect_pop (current_uiout); + + gdb_stdout = fp; + gdb_stderr = fp; + gdb_stdlog = fp; + gdb_stdtarg = fp; + gdb_stdtargerr = fp; + + TRY_CATCH (exception, RETURN_MASK_ERROR) + { + execute_command (pipe->gdb_cmd, from_tty); + } + + if (exception.reason < 0) + exception_print (gdb_stderr, exception); + + do_cleanups (cleanup); +} + +/* Execute the pipe command with argument ARG and FROM_TTY. */ + +static void +pipe_command (char *arg, int from_tty) +{ + struct pipe_obj *pipe = construct_pipe (arg); + 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); +}
Attachment:
ChangeLog
Description: Binary data
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |