xref: /freebsd-12.1/contrib/gdb/gdb/cli/cli-logging.c (revision f759f848)
1 /* Command-line output logging for GDB, the GNU debugger.
2 
3    Copyright 2003
4    Free Software Foundation, Inc.
5 
6    This file is part of GDB.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.  */
22 
23 #include "defs.h"
24 #include "gdbcmd.h"
25 #include "ui-out.h"
26 
27 #include "gdb_string.h"
28 
29 /* These hold the pushed copies of the gdb output files.
30    If NULL then nothing has yet been pushed.  */
31 struct saved_output_files
32 {
33   struct ui_file *out;
34   struct ui_file *err;
35   struct ui_file *log;
36   struct ui_file *targ;
37 };
38 static struct saved_output_files saved_output;
39 static char *saved_filename;
40 
41 static char *logging_filename;
42 int logging_overwrite, logging_redirect;
43 
44 /* If we've pushed output files, close them and pop them.  */
45 static void
pop_output_files(void)46 pop_output_files (void)
47 {
48   /* Only delete one of the files -- they are all set to the same
49      value.  */
50   ui_file_delete (gdb_stdout);
51   gdb_stdout = saved_output.out;
52   gdb_stderr = saved_output.err;
53   gdb_stdlog = saved_output.log;
54   gdb_stdtarg = saved_output.targ;
55   saved_output.out = NULL;
56   saved_output.err = NULL;
57   saved_output.log = NULL;
58   saved_output.targ = NULL;
59 
60   ui_out_redirect (uiout, NULL);
61 }
62 
63 /* This is a helper for the `set logging' command.  */
64 static void
handle_redirections(int from_tty)65 handle_redirections (int from_tty)
66 {
67   struct ui_file *output;
68 
69   if (saved_filename != NULL)
70     {
71       fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n",
72 			  saved_filename);
73       return;
74     }
75 
76   output = gdb_fopen (logging_filename, logging_overwrite ? "w" : "a");
77   if (output == NULL)
78     perror_with_name ("set logging");
79 
80   /* Redirects everything to gdb_stdout while this is running.  */
81   if (!logging_redirect)
82     {
83       output = tee_file_new (gdb_stdout, 0, output, 1);
84       if (output == NULL)
85 	perror_with_name ("set logging");
86       if (from_tty)
87 	fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n",
88 			    logging_filename);
89     }
90   else if (from_tty)
91     fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n",
92 			logging_filename);
93 
94   saved_filename = xstrdup (logging_filename);
95   saved_output.out = gdb_stdout;
96   saved_output.err = gdb_stderr;
97   saved_output.log = gdb_stdlog;
98   saved_output.targ = gdb_stdtarg;
99 
100   gdb_stdout = output;
101   gdb_stderr = output;
102   gdb_stdlog = output;
103   gdb_stdtarg = output;
104 
105   if (ui_out_redirect (uiout, gdb_stdout) < 0)
106     warning ("Current output protocol does not support redirection");
107 }
108 
109 static void
set_logging_on(char * args,int from_tty)110 set_logging_on (char *args, int from_tty)
111 {
112   char *rest = args;
113   if (rest && *rest)
114     {
115       xfree (logging_filename);
116       logging_filename = xstrdup (rest);
117     }
118   handle_redirections (from_tty);
119 }
120 
121 static void
set_logging_off(char * args,int from_tty)122 set_logging_off (char *args, int from_tty)
123 {
124   if (saved_filename == NULL)
125     return;
126 
127   pop_output_files ();
128   if (from_tty)
129     fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename);
130   xfree (saved_filename);
131   saved_filename = NULL;
132 }
133 
134 static void
set_logging_command(char * args,int from_tty)135 set_logging_command (char *args, int from_tty)
136 {
137   printf_unfiltered ("\"set logging\" lets you log output to a file.\n");
138   printf_unfiltered ("Usage: set logging on [FILENAME]\n");
139   printf_unfiltered ("       set logging off\n");
140   printf_unfiltered ("       set logging file FILENAME\n");
141   printf_unfiltered ("       set logging overwrite [on|off]\n");
142   printf_unfiltered ("       set logging redirect [on|off]\n");
143 }
144 
145 void
show_logging_command(char * args,int from_tty)146 show_logging_command (char *args, int from_tty)
147 {
148   if (saved_filename)
149     printf_unfiltered ("Currently logging to \"%s\".\n", saved_filename);
150   if (saved_filename == NULL
151       || strcmp (logging_filename, saved_filename) != 0)
152     printf_unfiltered ("Future logs will be written to %s.\n",
153 		       logging_filename);
154 
155   if (logging_overwrite)
156     printf_unfiltered ("Logs will overwrite the log file.\n");
157   else
158     printf_unfiltered ("Logs will be appended to the log file.\n");
159 
160   if (logging_redirect)
161     printf_unfiltered ("Output will be sent only to the log file.\n");
162   else
163     printf_unfiltered ("Output will be logged and displayed.\n");
164 }
165 
166 void
_initialize_cli_logging(void)167 _initialize_cli_logging (void)
168 {
169   static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
170 
171 
172   add_prefix_cmd ("logging", class_support, set_logging_command,
173 		  "Set logging options", &set_logging_cmdlist,
174 		  "set logging ", 0, &setlist);
175   add_prefix_cmd ("logging", class_support, show_logging_command,
176 		  "Show logging options", &show_logging_cmdlist,
177 		  "show logging ", 0, &showlist);
178   add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite,
179 			   "Set whether logging overwrites or appends "
180 			   "to the log file.\n",
181 			   "Show whether logging overwrites or appends "
182 			   "to the log file.\n",
183 			   NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
184   add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect,
185 			   "Set the logging output mode.\n"
186 			   "If redirect is off, output will go to both the "
187 			   "screen and the log file.\n"
188 			   "If redirect is on, output will go only to the log "
189 			   "file.",
190 			   "Show the logging output mode.\n"
191 			   "If redirect is off, output will go to both the "
192 			   "screen and the log file.\n"
193 			   "If redirect is on, output will go only to the log "
194 			   "file.",
195 			   NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
196   add_setshow_cmd ("file", class_support, var_filename, &logging_filename,
197 		   "Set the current logfile.", "Show the current logfile.",
198 		   NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
199   add_cmd ("on", class_support, set_logging_on,
200 	   "Enable logging.", &set_logging_cmdlist);
201   add_cmd ("off", class_support, set_logging_off,
202 	   "Disable logging.", &set_logging_cmdlist);
203 
204   logging_filename = xstrdup ("gdb.txt");
205 }
206