]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/cli/cli-logging.c
d6eb6c2b98f434c38cc0a217eb2cbba501437564
[thirdparty/binutils-gdb.git] / gdb / cli / cli-logging.c
1 /* Command-line output logging for GDB, the GNU debugger.
2
3 Copyright (C) 2003-2025 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20 #include "cli/cli-cmds.h"
21 #include "ui-out.h"
22 #include "interps.h"
23 #include "cli/cli-style.h"
24 #include "cli/cli-decode.h"
25
26 static std::string saved_filename;
27
28 static std::string logging_filename = "gdb.txt";
29 static void
30 show_logging_filename (struct ui_file *file, int from_tty,
31 struct cmd_list_element *c, const char *value)
32 {
33 gdb_printf (file, _("The current logfile is \"%ps\".\n"),
34 styled_string (file_name_style.style (), value));
35 }
36
37 static bool logging_overwrite;
38
39 static void
40 maybe_warn_already_logging ()
41 {
42 if (!saved_filename.empty ())
43 warning (_("Currently logging to %s. Turn the logging off and on to "
44 "make the new setting effective."), saved_filename.c_str ());
45 }
46
47 static void
48 set_logging_overwrite (const char *args,
49 int from_tty, struct cmd_list_element *c)
50 {
51 maybe_warn_already_logging ();
52 }
53
54 static void
55 show_logging_overwrite (struct ui_file *file, int from_tty,
56 struct cmd_list_element *c, const char *value)
57 {
58 if (logging_overwrite)
59 gdb_printf (file, _("on: Logging overwrites the log file.\n"));
60 else
61 gdb_printf (file, _("off: Logging appends to the log file.\n"));
62 }
63
64 /* Value as configured by the user. */
65 static bool logging_redirect;
66 static bool debug_redirect;
67
68 static void
69 set_logging_redirect (const char *args,
70 int from_tty, struct cmd_list_element *c)
71 {
72 maybe_warn_already_logging ();
73 }
74
75 static void
76 show_logging_redirect (struct ui_file *file, int from_tty,
77 struct cmd_list_element *c, const char *value)
78 {
79 if (logging_redirect)
80 gdb_printf (file, _("on: Output will go only to the log file.\n"));
81 else
82 gdb_printf
83 (file,
84 _("off: Output will go to both the screen and the log file.\n"));
85 }
86
87 static void
88 show_logging_debug_redirect (struct ui_file *file, int from_tty,
89 struct cmd_list_element *c, const char *value)
90 {
91 if (debug_redirect)
92 gdb_printf (file, _("on: Debug output will go only to the log file.\n"));
93 else
94 gdb_printf
95 (file,
96 _("off: Debug output will go to both the screen and the log file.\n"));
97 }
98
99 /* If we've pushed output files, close them and pop them. */
100 static void
101 pop_output_files (void)
102 {
103 current_interp_set_logging (NULL, false, false);
104
105 /* Stay consistent with handle_redirections. */
106 if (!current_uiout->is_mi_like_p ())
107 current_uiout->redirect (NULL);
108 }
109
110 /* This is a helper for the `set logging' command. */
111 static void
112 handle_redirections (int from_tty)
113 {
114 if (!saved_filename.empty ())
115 {
116 gdb_printf ("Already logging to %s.\n",
117 saved_filename.c_str ());
118 return;
119 }
120
121 stdio_file_up log (new no_terminal_escape_file ());
122 if (!log->open (logging_filename.c_str (), logging_overwrite ? "w" : "a"))
123 perror_with_name (_("set logging"));
124
125 /* Redirects everything to gdb_stdout while this is running. */
126 if (from_tty)
127 {
128 if (!logging_redirect)
129 gdb_printf ("Copying output to %s.\n",
130 logging_filename.c_str ());
131 else
132 gdb_printf ("Redirecting output to %s.\n",
133 logging_filename.c_str ());
134
135 if (!debug_redirect)
136 gdb_printf ("Copying debug output to %s.\n",
137 logging_filename.c_str ());
138 else
139 gdb_printf ("Redirecting debug output to %s.\n",
140 logging_filename.c_str ());
141 }
142
143 saved_filename = logging_filename;
144
145 /* Let the interpreter do anything it needs. */
146 current_interp_set_logging (std::move (log), logging_redirect,
147 debug_redirect);
148
149 /* Redirect the current ui-out object's output to the log. Use
150 gdb_stdout, not log, since the interpreter may have created a tee
151 that wraps the log. Don't do the redirect for MI, it confuses
152 MI's ui-out scheme. Note that we may get here with MI as current
153 interpreter, but with the current ui_out as a CLI ui_out, with
154 '-interpreter-exec console "set logging on"'. */
155 if (!current_uiout->is_mi_like_p ())
156 current_uiout->redirect (gdb_stdout);
157 }
158
159 static void
160 set_logging_on (const char *args, int from_tty)
161 {
162 const char *rest = args;
163
164 if (rest && *rest)
165 logging_filename = rest;
166
167 handle_redirections (from_tty);
168 }
169
170 static void
171 set_logging_off (const char *args, int from_tty)
172 {
173 if (saved_filename.empty ())
174 return;
175
176 pop_output_files ();
177 if (from_tty)
178 gdb_printf ("Done logging to %s.\n",
179 saved_filename.c_str ());
180 saved_filename.clear ();
181 }
182
183 static bool logging_enabled;
184
185 static void
186 set_logging_enabled (const char *args,
187 int from_tty, struct cmd_list_element *c)
188 {
189 if (logging_enabled)
190 set_logging_on (args, from_tty);
191 else
192 set_logging_off (args, from_tty);
193 }
194
195 static void
196 show_logging_enabled (struct ui_file *file, int from_tty,
197 struct cmd_list_element *c, const char *value)
198 {
199 if (logging_enabled)
200 gdb_printf (file, _("on: Logging is enabled.\n"));
201 else
202 gdb_printf (file, _("off: Logging is disabled.\n"));
203 }
204
205 INIT_GDB_FILE (cli_logging)
206 {
207 static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
208
209 /* Set/show logging. */
210 add_setshow_prefix_cmd ("logging", class_support,
211 _("Set logging options."),
212 _("Show logging options."),
213 &set_logging_cmdlist, &show_logging_cmdlist,
214 &setlist, &showlist);
215
216 /* Set/show logging overwrite. */
217 add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite, _("\
218 Set whether logging overwrites or appends to the log file."), _("\
219 Show whether logging overwrites or appends to the log file."), _("\
220 If set, logging overwrites the log file."),
221 set_logging_overwrite,
222 show_logging_overwrite,
223 &set_logging_cmdlist, &show_logging_cmdlist);
224
225 /* Set/show logging redirect. */
226 add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, _("\
227 Set the logging output mode."), _("\
228 Show the logging output mode."), _("\
229 If redirect is off, output will go to both the screen and the log file.\n\
230 If redirect is on, output will go only to the log file."),
231 set_logging_redirect,
232 show_logging_redirect,
233 &set_logging_cmdlist, &show_logging_cmdlist);
234
235 /* Set/show logging debugredirect. */
236 add_setshow_boolean_cmd ("debugredirect", class_support,
237 &debug_redirect, _("\
238 Set the logging debug output mode."), _("\
239 Show the logging debug output mode."), _("\
240 If debug redirect is off, debug will go to both the screen and the log file.\n\
241 If debug redirect is on, debug will go only to the log file."),
242 set_logging_redirect,
243 show_logging_debug_redirect,
244 &set_logging_cmdlist, &show_logging_cmdlist);
245
246 /* Set/show logging file. */
247 add_setshow_filename_cmd ("file", class_support, &logging_filename, _("\
248 Set the current logfile."), _("\
249 Show the current logfile."), _("\
250 The logfile is used when directing GDB's output."),
251 NULL,
252 show_logging_filename,
253 &set_logging_cmdlist, &show_logging_cmdlist);
254
255 /* Set/show logging enabled. */
256 set_show_commands setshow_logging_enabled_cmds
257 = add_setshow_boolean_cmd ("enabled", class_support, &logging_enabled,
258 _("Enable logging."),
259 _("Show whether logging is enabled."),
260 _("When on, enable logging."),
261 set_logging_enabled,
262 show_logging_enabled,
263 &set_logging_cmdlist, &show_logging_cmdlist);
264
265 /* Set logging on, deprecated alias. */
266 cmd_list_element *set_logging_on_cmd
267 = add_alias_cmd ("on", setshow_logging_enabled_cmds.set, class_support,
268 false, &set_logging_cmdlist);
269 deprecate_cmd (set_logging_on_cmd, "set logging enabled on");
270 set_logging_on_cmd->default_args = "on";
271
272 /* Set logging off, deprecated alias. */
273 cmd_list_element *set_logging_off_cmd
274 = add_alias_cmd ("off", setshow_logging_enabled_cmds.set, class_support,
275 false, &set_logging_cmdlist);
276 deprecate_cmd (set_logging_off_cmd, "set logging enabled off");
277 set_logging_off_cmd->default_args = "off";
278 }