1130803Smarcel/* Command-line output logging for GDB, the GNU debugger.
2130803Smarcel
3130803Smarcel   Copyright 2003
4130803Smarcel   Free Software Foundation, Inc.
5130803Smarcel
6130803Smarcel   This file is part of GDB.
7130803Smarcel
8130803Smarcel   This program is free software; you can redistribute it and/or modify
9130803Smarcel   it under the terms of the GNU General Public License as published by
10130803Smarcel   the Free Software Foundation; either version 2 of the License, or
11130803Smarcel   (at your option) any later version.
12130803Smarcel
13130803Smarcel   This program is distributed in the hope that it will be useful,
14130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130803Smarcel   GNU General Public License for more details.
17130803Smarcel
18130803Smarcel   You should have received a copy of the GNU General Public License
19130803Smarcel   along with this program; if not, write to the Free Software
20130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
21130803Smarcel   Boston, MA 02111-1307, USA.  */
22130803Smarcel
23130803Smarcel#include "defs.h"
24130803Smarcel#include "gdbcmd.h"
25130803Smarcel#include "ui-out.h"
26130803Smarcel
27130803Smarcel#include "gdb_string.h"
28130803Smarcel
29130803Smarcel/* These hold the pushed copies of the gdb output files.
30130803Smarcel   If NULL then nothing has yet been pushed.  */
31130803Smarcelstruct saved_output_files
32130803Smarcel{
33130803Smarcel  struct ui_file *out;
34130803Smarcel  struct ui_file *err;
35130803Smarcel  struct ui_file *log;
36130803Smarcel  struct ui_file *targ;
37130803Smarcel};
38130803Smarcelstatic struct saved_output_files saved_output;
39130803Smarcelstatic char *saved_filename;
40130803Smarcel
41130803Smarcelstatic char *logging_filename;
42130803Smarcelint logging_overwrite, logging_redirect;
43130803Smarcel
44130803Smarcel/* If we've pushed output files, close them and pop them.  */
45130803Smarcelstatic void
46130803Smarcelpop_output_files (void)
47130803Smarcel{
48130803Smarcel  /* Only delete one of the files -- they are all set to the same
49130803Smarcel     value.  */
50130803Smarcel  ui_file_delete (gdb_stdout);
51130803Smarcel  gdb_stdout = saved_output.out;
52130803Smarcel  gdb_stderr = saved_output.err;
53130803Smarcel  gdb_stdlog = saved_output.log;
54130803Smarcel  gdb_stdtarg = saved_output.targ;
55130803Smarcel  saved_output.out = NULL;
56130803Smarcel  saved_output.err = NULL;
57130803Smarcel  saved_output.log = NULL;
58130803Smarcel  saved_output.targ = NULL;
59130803Smarcel
60130803Smarcel  ui_out_redirect (uiout, NULL);
61130803Smarcel}
62130803Smarcel
63130803Smarcel/* This is a helper for the `set logging' command.  */
64130803Smarcelstatic void
65130803Smarcelhandle_redirections (int from_tty)
66130803Smarcel{
67130803Smarcel  struct ui_file *output;
68130803Smarcel
69130803Smarcel  if (saved_filename != NULL)
70130803Smarcel    {
71130803Smarcel      fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n",
72130803Smarcel			  saved_filename);
73130803Smarcel      return;
74130803Smarcel    }
75130803Smarcel
76130803Smarcel  output = gdb_fopen (logging_filename, logging_overwrite ? "w" : "a");
77130803Smarcel  if (output == NULL)
78130803Smarcel    perror_with_name ("set logging");
79130803Smarcel
80130803Smarcel  /* Redirects everything to gdb_stdout while this is running.  */
81130803Smarcel  if (!logging_redirect)
82130803Smarcel    {
83130803Smarcel      output = tee_file_new (gdb_stdout, 0, output, 1);
84130803Smarcel      if (output == NULL)
85130803Smarcel	perror_with_name ("set logging");
86130803Smarcel      if (from_tty)
87130803Smarcel	fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n",
88130803Smarcel			    logging_filename);
89130803Smarcel    }
90130803Smarcel  else if (from_tty)
91130803Smarcel    fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n",
92130803Smarcel			logging_filename);
93130803Smarcel
94130803Smarcel  saved_filename = xstrdup (logging_filename);
95130803Smarcel  saved_output.out = gdb_stdout;
96130803Smarcel  saved_output.err = gdb_stderr;
97130803Smarcel  saved_output.log = gdb_stdlog;
98130803Smarcel  saved_output.targ = gdb_stdtarg;
99130803Smarcel
100130803Smarcel  gdb_stdout = output;
101130803Smarcel  gdb_stderr = output;
102130803Smarcel  gdb_stdlog = output;
103130803Smarcel  gdb_stdtarg = output;
104130803Smarcel
105130803Smarcel  if (ui_out_redirect (uiout, gdb_stdout) < 0)
106130803Smarcel    warning ("Current output protocol does not support redirection");
107130803Smarcel}
108130803Smarcel
109130803Smarcelstatic void
110130803Smarcelset_logging_on (char *args, int from_tty)
111130803Smarcel{
112130803Smarcel  char *rest = args;
113130803Smarcel  if (rest && *rest)
114130803Smarcel    {
115130803Smarcel      xfree (logging_filename);
116130803Smarcel      logging_filename = xstrdup (rest);
117130803Smarcel    }
118130803Smarcel  handle_redirections (from_tty);
119130803Smarcel}
120130803Smarcel
121130803Smarcelstatic void
122130803Smarcelset_logging_off (char *args, int from_tty)
123130803Smarcel{
124130803Smarcel  if (saved_filename == NULL)
125130803Smarcel    return;
126130803Smarcel
127130803Smarcel  pop_output_files ();
128130803Smarcel  if (from_tty)
129130803Smarcel    fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename);
130130803Smarcel  xfree (saved_filename);
131130803Smarcel  saved_filename = NULL;
132130803Smarcel}
133130803Smarcel
134130803Smarcelstatic void
135130803Smarcelset_logging_command (char *args, int from_tty)
136130803Smarcel{
137130803Smarcel  printf_unfiltered ("\"set logging\" lets you log output to a file.\n");
138130803Smarcel  printf_unfiltered ("Usage: set logging on [FILENAME]\n");
139130803Smarcel  printf_unfiltered ("       set logging off\n");
140130803Smarcel  printf_unfiltered ("       set logging file FILENAME\n");
141130803Smarcel  printf_unfiltered ("       set logging overwrite [on|off]\n");
142130803Smarcel  printf_unfiltered ("       set logging redirect [on|off]\n");
143130803Smarcel}
144130803Smarcel
145130803Smarcelvoid
146130803Smarcelshow_logging_command (char *args, int from_tty)
147130803Smarcel{
148130803Smarcel  if (saved_filename)
149130803Smarcel    printf_unfiltered ("Currently logging to \"%s\".\n", saved_filename);
150130803Smarcel  if (saved_filename == NULL
151130803Smarcel      || strcmp (logging_filename, saved_filename) != 0)
152130803Smarcel    printf_unfiltered ("Future logs will be written to %s.\n",
153130803Smarcel		       logging_filename);
154130803Smarcel
155130803Smarcel  if (logging_overwrite)
156130803Smarcel    printf_unfiltered ("Logs will overwrite the log file.\n");
157130803Smarcel  else
158130803Smarcel    printf_unfiltered ("Logs will be appended to the log file.\n");
159130803Smarcel
160130803Smarcel  if (logging_redirect)
161130803Smarcel    printf_unfiltered ("Output will be sent only to the log file.\n");
162130803Smarcel  else
163130803Smarcel    printf_unfiltered ("Output will be logged and displayed.\n");
164130803Smarcel}
165130803Smarcel
166130803Smarcelvoid
167130803Smarcel_initialize_cli_logging (void)
168130803Smarcel{
169130803Smarcel  static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
170130803Smarcel
171130803Smarcel
172130803Smarcel  add_prefix_cmd ("logging", class_support, set_logging_command,
173130803Smarcel		  "Set logging options", &set_logging_cmdlist,
174130803Smarcel		  "set logging ", 0, &setlist);
175130803Smarcel  add_prefix_cmd ("logging", class_support, show_logging_command,
176130803Smarcel		  "Show logging options", &show_logging_cmdlist,
177130803Smarcel		  "show logging ", 0, &showlist);
178130803Smarcel  add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite,
179130803Smarcel			   "Set whether logging overwrites or appends "
180130803Smarcel			   "to the log file.\n",
181130803Smarcel			   "Show whether logging overwrites or appends "
182130803Smarcel			   "to the log file.\n",
183130803Smarcel			   NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
184130803Smarcel  add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect,
185130803Smarcel			   "Set the logging output mode.\n"
186130803Smarcel			   "If redirect is off, output will go to both the "
187130803Smarcel			   "screen and the log file.\n"
188130803Smarcel			   "If redirect is on, output will go only to the log "
189130803Smarcel			   "file.",
190130803Smarcel			   "Show the logging output mode.\n"
191130803Smarcel			   "If redirect is off, output will go to both the "
192130803Smarcel			   "screen and the log file.\n"
193130803Smarcel			   "If redirect is on, output will go only to the log "
194130803Smarcel			   "file.",
195130803Smarcel			   NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
196130803Smarcel  add_setshow_cmd ("file", class_support, var_filename, &logging_filename,
197130803Smarcel		   "Set the current logfile.", "Show the current logfile.",
198130803Smarcel		   NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
199130803Smarcel  add_cmd ("on", class_support, set_logging_on,
200130803Smarcel	   "Enable logging.", &set_logging_cmdlist);
201130803Smarcel  add_cmd ("off", class_support, set_logging_off,
202130803Smarcel	   "Disable logging.", &set_logging_cmdlist);
203130803Smarcel
204130803Smarcel  logging_filename = xstrdup ("gdb.txt");
205130803Smarcel}
206