From: Abhijit Halder <abhijit.k.halder@gmail.com>
To: gdb-patches@sourceware.org
Subject: Re: [PATCH] gdb output pipelining to shell
Date: Sun, 17 Jul 2011 20:26:00 -0000 [thread overview]
Message-ID: <CAOhZP9yq=ZKk_g9zmShximE8FEedG3h0Nc4=D_5gGJNpPd4OHg@mail.gmail.com> (raw)
In-Reply-To: <CAOhZP9xjux0suHVpSz+b+SwyPABUEsKcAZf4rXu4ZQKMW0njJg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2808 bytes --]
A small correction. Re-submitting the patch. The earlier patch was not
able to handle below situation:
(gdb) p '|' | { less }
On Sat, Jul 16, 2011 at 3:38 PM, Abhijit Halder
<abhijit.k.halder@gmail.com> wrote:
> On Sat, Jul 16, 2011 at 3:17 PM, Eli Zaretskii <eliz@gnu.org> wrote:
>>> Date: Sat, 16 Jul 2011 14:12:35 +0530
>>> From: Abhijit Halder <abhijit.k.halder@gmail.com>
>>>
>>> I have implemented a feature which will allow one to pass the output
>>> of any gdb command to the shell for further processing.
>>
>> Thanks.
>>
>> If this is accepted, we will need a corresponding addition to the
>> manual.
>>
>>> + for (cpos = spos; (cpos = memchr (cpos, '"', (sh_cmd-cpos))) != NULL; cpos++)
>>> + quote_cnt++;
>>> + spos = (sh_cmd + 1);
>>> + if ((quote_cnt % 2) == 0 || (sh_cmd = strchr (spos, '|')) == NULL)
>>> + break;
>>
>> I'm not sure I understand this (comments would be helpful). Are you
>> assuming that quote characters `"' in shell commands cannot be
>> escaped, e.g. with a backslash? And what about quoting with a single
>> quote character ("'")?
>>
> Any pipe ('|' character), not within double quote will be considered
> as either a bitwise-OR operator or a pipe between gdb and shell.
> String after pipe (not within double quote) will be considered as
> shell command if (and only if) it is encapsulated within opening and
> closing braces ('{' and '}') . The shell command can surely contain
> double quote, even braces. There is no validation done for shell
> command.
>
>>> + if (*cpos != '{')
>>> + return NULL;
>>> +
>>> + *cpos = ' ';
>>> +
>>> + cpos = epos;
>>> + while (isspace(*cpos))
>>> + cpos--;
>>> +
>>> + if (*cpos != '}')
>>> + return NULL;
>>
>> What is this magic about {...} that you are removing? Again, comments
>> could help.
>>
> Here I am removing the braces from the shell command. An example will
> help in understanding this:
> (gdb) thread apply all bt | { grep "foo" }
> This will be a valid command. { grep "foo" } will be considered as
> shell command and we need to erase the braces part of it to make it a
> valid shell command.
>>> +
>>> + *cpos = ' ';
>>> + }
>>> +
>>> + if (sh_cmd)
>>> + *sh_cmd++ = '\0';
>>> +
>>> + return sh_cmd;
>>
>> This butchers the string passed to execute_command. Are you sure all
>> the callers of execute_command can safely deal with that? What if the
>> string is a constant string, for example?
>>
> The new code path will be executed only when one will enter a command
> containing pipeline between gdb and shell. In that case the string
> passed to execute_command must not be a constant string (since it is
> user input from gdb prompt). Hence we are safe.
>
[-- Attachment #2: gdb-shell-integration-new.patch --]
[-- Type: text/x-patch, Size: 3499 bytes --]
diff -rup src//gdb/top.c dst//gdb/top.c
--- src//gdb/top.c 2011-06-28 00:51:50.000000000 +0530
+++ dst//gdb/top.c 2011-07-16 23:05:46.745978992 +0530
@@ -48,6 +48,7 @@
#include "event-loop.h"
#include "gdbthread.h"
#include "python/python.h"
+#include "ui-file.h"
/* readline include files. */
#include "readline/readline.h"
@@ -358,6 +359,68 @@ prepare_execute_command (void)
return cleanup;
}
+char *
+parse_for_shell_command (char *p)
+{
+ char *sh_cmd, *cpos, *spos, *epos;
+ int quote_cnt = 0;
+
+ if ((sh_cmd = strchr (p, '|')) != NULL)
+ {
+ spos = p;
+ epos = p + strlen (p) - 1;
+
+ for (;;)
+ {
+ for (cpos = spos; (cpos = memchr (cpos, '"', (sh_cmd-cpos))) != NULL; cpos++)
+ quote_cnt++;
+ spos = (sh_cmd + 1);
+ if ((quote_cnt % 2) == 0 || (sh_cmd = strchr (spos, '|')) == NULL)
+ break;
+ }
+
+ if (sh_cmd == NULL)
+ return NULL;
+
+ cpos = spos;
+ while (isspace(*cpos))
+ cpos++;
+
+ if (*cpos != '{')
+ return parse_for_shell_command (cpos);
+
+ *cpos = ' ';
+
+ cpos = epos;
+ while (isspace(*cpos))
+ cpos--;
+
+ if (*cpos != '}')
+ return parse_for_shell_command (cpos);
+
+ *cpos = ' ';
+ }
+
+ if (sh_cmd)
+ *sh_cmd++ = '\0';
+
+ return sh_cmd;
+}
+
+/* Run execute_command for P and FROM_TTY. Write output in pipe,
+ do not display it to the screen. */
+
+void
+execute_command_to_pipe (char *p, int from_tty, FILE *pipe)
+{
+ FILE *file;
+
+ file = gdb_modify_io (gdb_stdout, pipe);
+ execute_command (p, from_tty);
+ pipe = gdb_modify_io (gdb_stdout, file);
+ pclose (pipe);
+}
+
/* Execute the line P as a command, in the current user context.
Pass FROM_TTY as second argument to the defining function. */
@@ -368,7 +431,16 @@ execute_command (char *p, int from_tty)
struct cmd_list_element *c;
enum language flang;
static int warned = 0;
- char *line;
+ char *line, *sh_cmd;
+
+ if ((sh_cmd = parse_for_shell_command (p)) != NULL)
+ {
+ FILE *pipe;
+
+ pipe = popen (sh_cmd, "w");
+ execute_command_to_pipe (p, from_tty, pipe);
+ return;
+ }
cleanup = prepare_execute_command ();
diff -rup src//gdb/ui-file.c dst//gdb/ui-file.c
--- src//gdb/ui-file.c 2011-05-14 11:14:36.000000000 +0530
+++ dst//gdb/ui-file.c 2011-07-15 13:49:34.999910332 +0530
@@ -617,6 +617,21 @@ struct ui_file *
stdio_fileopen (FILE *file)
{
return stdio_file_new (file, 0);
+
+}
+
+FILE *
+gdb_modify_io (struct ui_file *file, FILE *iostream_new)
+{
+ FILE *iostream_old;
+ struct stdio_file *stdio = ui_file_data (file);
+
+ if (stdio->magic != &stdio_file_magic)
+ internal_error (__FILE__, __LINE__,
+ _("gdb_modify_io: bad magic number"));
+ iostream_old = stdio->file;
+ stdio->file = iostream_new;
+ return iostream_old;
}
struct ui_file *
diff -rup src//gdb/ui-file.h dst//gdb/ui-file.h
--- src//gdb/ui-file.h 2011-05-13 22:58:20.000000000 +0530
+++ dst//gdb/ui-file.h 2011-07-15 13:48:54.603912199 +0530
@@ -126,6 +126,9 @@ extern struct ui_file *stdio_fileopen (F
/* Open NAME returning an STDIO based UI_FILE. */
extern struct ui_file *gdb_fopen (char *name, char *mode);
+/* Modify the file pointer of an STDIO based UI_FILE. */
+FILE *gdb_modify_io (struct ui_file *file, FILE *iostream_new);
+
/* Create a file which writes to both ONE and TWO. CLOSE_ONE
and CLOSE_TWO indicate whether the original files should be
closed when the new file is closed. */
next prev parent reply other threads:[~2011-07-16 18:06 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-16 10:09 Abhijit Halder
2011-07-16 14:49 ` Eli Zaretskii
2011-07-16 18:06 ` Abhijit Halder
2011-07-17 20:26 ` Abhijit Halder [this message]
2011-07-18 18:23 ` Abhijit Halder
2011-07-18 20:15 ` Abhijit Halder
2011-07-19 8:50 ` Abhijit Halder
2011-07-19 10:31 ` Abhijit Halder
[not found] ` <CAOhZP9yZ01y8KY9BEjWvtXnJw1jEjTZxPcTNK6h+A9dn-WZWwQ@mail.gmail.com>
2011-07-20 13:17 ` Abhijit Halder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAOhZP9yq=ZKk_g9zmShximE8FEedG3h0Nc4=D_5gGJNpPd4OHg@mail.gmail.com' \
--to=abhijit.k.halder@gmail.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox