1 /* Command-line output logging for GDB, the GNU debugger.
3 Copyright (C) 2003-2017 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
25 /* These hold the pushed copies of the gdb output files.
26 If NULL then nothing has yet been pushed. */
27 struct saved_output_files
33 struct ui_file *targerr;
35 static struct saved_output_files saved_output;
36 static char *saved_filename;
38 static char *logging_filename;
40 show_logging_filename (struct ui_file *file, int from_tty,
41 struct cmd_list_element *c, const char *value)
43 fprintf_filtered (file, _("The current logfile is \"%s\".\n"),
47 static int logging_overwrite;
50 set_logging_overwrite (char *args, int from_tty, struct cmd_list_element *c)
53 warning (_("Currently logging to %s. Turn the logging off and on to "
54 "make the new setting effective."), saved_filename);
58 show_logging_overwrite (struct ui_file *file, int from_tty,
59 struct cmd_list_element *c, const char *value)
61 fprintf_filtered (file,
62 _("Whether logging overwrites or "
63 "appends to the log file is %s.\n"),
67 /* Value as configured by the user. */
68 static int logging_redirect;
70 /* The on-disk file in use if logging is currently active together
71 with redirection turned off (and therefore using tee_file_new).
72 For active logging with redirection the on-disk file is directly in
73 GDB_STDOUT and this variable is NULL. */
74 static struct ui_file *logging_no_redirect_file;
77 set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c)
79 ui_file_up destroy_old_stdout;
80 struct ui_file *output, *new_logging_no_redirect_file;
81 struct ui_out *uiout = current_uiout;
83 if (saved_filename == NULL
84 || (logging_redirect != 0 && logging_no_redirect_file == NULL)
85 || (logging_redirect == 0 && logging_no_redirect_file != NULL))
88 if (logging_redirect != 0)
90 gdb_assert (logging_no_redirect_file != NULL);
92 /* ui_out_redirect still has not been called for next
94 destroy_old_stdout.reset (gdb_stdout);
96 output = logging_no_redirect_file;
97 new_logging_no_redirect_file = NULL;
100 fprintf_unfiltered (saved_output.out, "Redirecting output to %s.\n",
105 gdb_assert (logging_no_redirect_file == NULL);
106 output = new tee_file (saved_output.out, 0, gdb_stdout, 0);
107 new_logging_no_redirect_file = gdb_stdout;
110 fprintf_unfiltered (saved_output.out, "Copying output to %s.\n",
114 /* Give the current interpreter a chance to do anything special that
115 it might need for logging, such as updating other channels. */
116 if (current_interp_set_logging (1, output, NULL) == 0)
121 gdb_stdtarg = output;
122 gdb_stdtargerr = output;
125 logging_no_redirect_file = new_logging_no_redirect_file;
127 /* There is a former output pushed on the ui_out_redirect stack. We
128 want to replace it by OUTPUT so we must pop the former value
129 first. Ideally, we should either do both the pop and push or do
132 uiout->redirect (NULL);
133 uiout->redirect (output);
137 show_logging_redirect (struct ui_file *file, int from_tty,
138 struct cmd_list_element *c, const char *value)
140 fprintf_filtered (file, _("The logging output mode is %s.\n"), value);
143 /* If we've pushed output files, close them and pop them. */
145 pop_output_files (void)
147 if (logging_no_redirect_file)
149 delete logging_no_redirect_file;
150 logging_no_redirect_file = NULL;
153 if (current_interp_set_logging (0, NULL, NULL) == 0)
155 /* Only delete one of the files -- they are all set to the same
159 gdb_stdout = saved_output.out;
160 gdb_stderr = saved_output.err;
161 gdb_stdlog = saved_output.log;
162 gdb_stdtarg = saved_output.targ;
163 gdb_stdtargerr = saved_output.targerr;
166 saved_output.out = NULL;
167 saved_output.err = NULL;
168 saved_output.log = NULL;
169 saved_output.targ = NULL;
170 saved_output.targerr = NULL;
172 /* Stay consistent with handle_redirections. */
173 if (!current_uiout->is_mi_like_p ())
174 current_uiout->redirect (NULL);
177 /* This is a helper for the `set logging' command. */
179 handle_redirections (int from_tty)
182 ui_file_up no_redirect_file;
184 if (saved_filename != NULL)
186 fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n",
191 stdio_file_up log (new stdio_file ());
192 if (!log->open (logging_filename, logging_overwrite ? "w" : "a"))
193 perror_with_name (_("set logging"));
195 /* Redirects everything to gdb_stdout while this is running. */
196 if (!logging_redirect)
198 no_redirect_file = std::move (log);
199 output.reset (new tee_file (gdb_stdout, 0, no_redirect_file.get (), 0));
202 fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n",
207 gdb_assert (logging_no_redirect_file == NULL);
208 output = std::move (log);
211 fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n",
215 saved_filename = xstrdup (logging_filename);
216 saved_output.out = gdb_stdout;
217 saved_output.err = gdb_stderr;
218 saved_output.log = gdb_stdlog;
219 saved_output.targ = gdb_stdtarg;
220 saved_output.targerr = gdb_stdtargerr;
222 /* Let the interpreter do anything it needs. */
223 if (current_interp_set_logging (1, output.get (),
224 no_redirect_file.get ()) == 0)
226 gdb_stdout = output.get ();
227 gdb_stdlog = output.get ();
228 gdb_stderr = output.get ();
229 gdb_stdtarg = output.get ();
230 gdb_stdtargerr = output.get ();
234 logging_no_redirect_file = no_redirect_file.release ();
236 /* Don't do the redirect for MI, it confuses MI's ui-out scheme. */
237 if (!current_uiout->is_mi_like_p ())
238 current_uiout->redirect (gdb_stdout);
242 set_logging_on (char *args, int from_tty)
248 xfree (logging_filename);
249 logging_filename = xstrdup (rest);
251 handle_redirections (from_tty);
255 set_logging_off (char *args, int from_tty)
257 if (saved_filename == NULL)
262 fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename);
263 xfree (saved_filename);
264 saved_filename = NULL;
268 set_logging_command (char *args, int from_tty)
270 printf_unfiltered (_("\"set logging\" lets you log output to a file.\n"
271 "Usage: set logging on [FILENAME]\n"
273 " set logging file FILENAME\n"
274 " set logging overwrite [on|off]\n"
275 " set logging redirect [on|off]\n"));
279 show_logging_command (char *args, int from_tty)
282 printf_unfiltered (_("Currently logging to \"%s\".\n"), saved_filename);
283 if (saved_filename == NULL
284 || strcmp (logging_filename, saved_filename) != 0)
285 printf_unfiltered (_("Future logs will be written to %s.\n"),
288 if (logging_overwrite)
289 printf_unfiltered (_("Logs will overwrite the log file.\n"));
291 printf_unfiltered (_("Logs will be appended to the log file.\n"));
295 if (logging_redirect)
296 printf_unfiltered (_("Output is being sent only to the log file.\n"));
298 printf_unfiltered (_("Output is being logged and displayed.\n"));
302 if (logging_redirect)
303 printf_unfiltered (_("Output will be sent only to the log file.\n"));
305 printf_unfiltered (_("Output will be logged and displayed.\n"));
309 /* Provide a prototype to silence -Wmissing-prototypes. */
310 extern initialize_file_ftype _initialize_cli_logging;
313 _initialize_cli_logging (void)
315 static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
317 add_prefix_cmd ("logging", class_support, set_logging_command,
318 _("Set logging options"), &set_logging_cmdlist,
319 "set logging ", 0, &setlist);
320 add_prefix_cmd ("logging", class_support, show_logging_command,
321 _("Show logging options"), &show_logging_cmdlist,
322 "show logging ", 0, &showlist);
323 add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite, _("\
324 Set whether logging overwrites or appends to the log file."), _("\
325 Show whether logging overwrites or appends to the log file."), _("\
326 If set, logging overrides the log file."),
327 set_logging_overwrite,
328 show_logging_overwrite,
329 &set_logging_cmdlist, &show_logging_cmdlist);
330 add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, _("\
331 Set the logging output mode."), _("\
332 Show the logging output mode."), _("\
333 If redirect is off, output will go to both the screen and the log file.\n\
334 If redirect is on, output will go only to the log file."),
335 set_logging_redirect,
336 show_logging_redirect,
337 &set_logging_cmdlist, &show_logging_cmdlist);
338 add_setshow_filename_cmd ("file", class_support, &logging_filename, _("\
339 Set the current logfile."), _("\
340 Show the current logfile."), _("\
341 The logfile is used when directing GDB's output."),
343 show_logging_filename,
344 &set_logging_cmdlist, &show_logging_cmdlist);
345 add_cmd ("on", class_support, set_logging_on,
346 _("Enable logging."), &set_logging_cmdlist);
347 add_cmd ("off", class_support, set_logging_off,
348 _("Disable logging."), &set_logging_cmdlist);
350 logging_filename = xstrdup ("gdb.txt");