1130803Smarcel/* MI Command Set - environment commands.
2130803Smarcel
3130803Smarcel   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   Contributed by Red Hat Inc.
6130803Smarcel
7130803Smarcel   This file is part of GDB.
8130803Smarcel
9130803Smarcel   This program is free software; you can redistribute it and/or modify
10130803Smarcel   it under the terms of the GNU General Public License as published by
11130803Smarcel   the Free Software Foundation; either version 2 of the License, or
12130803Smarcel   (at your option) any later version.
13130803Smarcel
14130803Smarcel   This program is distributed in the hope that it will be useful,
15130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
16130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17130803Smarcel   GNU General Public License for more details.
18130803Smarcel
19130803Smarcel   You should have received a copy of the GNU General Public License
20130803Smarcel   along with this program; if not, write to the Free Software
21130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
22130803Smarcel   Boston, MA 02111-1307, USA.  */
23130803Smarcel
24130803Smarcel#include "defs.h"
25130803Smarcel#include "inferior.h"
26130803Smarcel#include "value.h"
27130803Smarcel#include "mi-out.h"
28130803Smarcel#include "mi-cmds.h"
29130803Smarcel#include "mi-getopt.h"
30130803Smarcel#include "symtab.h"
31130803Smarcel#include "target.h"
32130803Smarcel#include "environ.h"
33130803Smarcel#include "command.h"
34130803Smarcel#include "ui-out.h"
35130803Smarcel#include "top.h"
36130803Smarcel
37130803Smarcel#include "gdb_string.h"
38130803Smarcel#include "gdb_stat.h"
39130803Smarcel
40130803Smarcelstatic void env_mod_path (char *dirname, char **which_path);
41130803Smarcelextern void _initialize_mi_cmd_env (void);
42130803Smarcel
43130803Smarcelstatic const char path_var_name[] = "PATH";
44130803Smarcelstatic char *orig_path = NULL;
45130803Smarcel
46130803Smarcel/* The following is copied from mi-main.c so for m1 and below we can
47130803Smarcel   perform old behavior and use cli commands.  If ARGS is non-null,
48130803Smarcel   append it to the CMD.  */
49130803Smarcelstatic void
50130803Smarcelenv_execute_cli_command (const char *cmd, const char *args)
51130803Smarcel{
52130803Smarcel  if (cmd != 0)
53130803Smarcel    {
54130803Smarcel      struct cleanup *old_cleanups;
55130803Smarcel      char *run;
56130803Smarcel      if (args != NULL)
57130803Smarcel	xasprintf (&run, "%s %s", cmd, args);
58130803Smarcel      else
59130803Smarcel	run = xstrdup (cmd);
60130803Smarcel      old_cleanups = make_cleanup (xfree, run);
61130803Smarcel      execute_command ( /*ui */ run, 0 /*from_tty */ );
62130803Smarcel      do_cleanups (old_cleanups);
63130803Smarcel      return;
64130803Smarcel    }
65130803Smarcel}
66130803Smarcel
67130803Smarcel
68130803Smarcel/* Print working directory.  */
69130803Smarcelenum mi_cmd_result
70130803Smarcelmi_cmd_env_pwd (char *command, char **argv, int argc)
71130803Smarcel{
72130803Smarcel  if (argc > 0)
73130803Smarcel    error ("mi_cmd_env_pwd: No arguments required");
74130803Smarcel
75130803Smarcel  if (mi_version (uiout) < 2)
76130803Smarcel    {
77130803Smarcel      env_execute_cli_command ("pwd", NULL);
78130803Smarcel      return MI_CMD_DONE;
79130803Smarcel    }
80130803Smarcel
81130803Smarcel  /* Otherwise the mi level is 2 or higher.  */
82130803Smarcel
83130803Smarcel  getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
84130803Smarcel  ui_out_field_string (uiout, "cwd", gdb_dirbuf);
85130803Smarcel
86130803Smarcel  return MI_CMD_DONE;
87130803Smarcel}
88130803Smarcel
89130803Smarcel/* Change working directory.  */
90130803Smarcelenum mi_cmd_result
91130803Smarcelmi_cmd_env_cd (char *command, char **argv, int argc)
92130803Smarcel{
93130803Smarcel  if (argc == 0 || argc > 1)
94130803Smarcel    error ("mi_cmd_env_cd: Usage DIRECTORY");
95130803Smarcel
96130803Smarcel  env_execute_cli_command ("cd", argv[0]);
97130803Smarcel
98130803Smarcel  return MI_CMD_DONE;
99130803Smarcel}
100130803Smarcel
101130803Smarcelstatic void
102130803Smarcelenv_mod_path (char *dirname, char **which_path)
103130803Smarcel{
104130803Smarcel  if (dirname == 0 || dirname[0] == '\0')
105130803Smarcel    return;
106130803Smarcel
107130803Smarcel  /* Call add_path with last arg 0 to indicate not to parse for
108130803Smarcel     separator characters.  */
109130803Smarcel  add_path (dirname, which_path, 0);
110130803Smarcel}
111130803Smarcel
112130803Smarcel/* Add one or more directories to start of executable search path.  */
113130803Smarcelenum mi_cmd_result
114130803Smarcelmi_cmd_env_path (char *command, char **argv, int argc)
115130803Smarcel{
116130803Smarcel  char *exec_path;
117130803Smarcel  char *env;
118130803Smarcel  int reset = 0;
119130803Smarcel  int optind = 0;
120130803Smarcel  int i;
121130803Smarcel  char *optarg;
122130803Smarcel  enum opt
123130803Smarcel    {
124130803Smarcel      RESET_OPT
125130803Smarcel    };
126130803Smarcel  static struct mi_opt opts[] =
127130803Smarcel  {
128130803Smarcel    {"r", RESET_OPT, 0},
129130803Smarcel    0
130130803Smarcel  };
131130803Smarcel
132130803Smarcel  dont_repeat ();
133130803Smarcel
134130803Smarcel  if (mi_version (uiout) < 2)
135130803Smarcel    {
136130803Smarcel      for (i = argc - 1; i >= 0; --i)
137130803Smarcel	env_execute_cli_command ("path", argv[i]);
138130803Smarcel      return MI_CMD_DONE;
139130803Smarcel    }
140130803Smarcel
141130803Smarcel  /* Otherwise the mi level is 2 or higher.  */
142130803Smarcel  while (1)
143130803Smarcel    {
144130803Smarcel      int opt = mi_getopt ("mi_cmd_env_path", argc, argv, opts,
145130803Smarcel                           &optind, &optarg);
146130803Smarcel      if (opt < 0)
147130803Smarcel        break;
148130803Smarcel      switch ((enum opt) opt)
149130803Smarcel        {
150130803Smarcel        case RESET_OPT:
151130803Smarcel          reset = 1;
152130803Smarcel          break;
153130803Smarcel        }
154130803Smarcel    }
155130803Smarcel  argv += optind;
156130803Smarcel  argc -= optind;
157130803Smarcel
158130803Smarcel
159130803Smarcel  if (reset)
160130803Smarcel    {
161130803Smarcel      /* Reset implies resetting to original path first.  */
162130803Smarcel      exec_path = xstrdup (orig_path);
163130803Smarcel    }
164130803Smarcel  else
165130803Smarcel    {
166130803Smarcel      /* Otherwise, get current path to modify.  */
167130803Smarcel      env = get_in_environ (inferior_environ, path_var_name);
168130803Smarcel
169130803Smarcel      /* Can be null if path is not set.  */
170130803Smarcel      if (!env)
171130803Smarcel        env = "";
172130803Smarcel      exec_path = xstrdup (env);
173130803Smarcel    }
174130803Smarcel
175130803Smarcel  for (i = argc - 1; i >= 0; --i)
176130803Smarcel    env_mod_path (argv[i], &exec_path);
177130803Smarcel
178130803Smarcel  set_in_environ (inferior_environ, path_var_name, exec_path);
179130803Smarcel  xfree (exec_path);
180130803Smarcel  env = get_in_environ (inferior_environ, path_var_name);
181130803Smarcel  ui_out_field_string (uiout, "path", env);
182130803Smarcel
183130803Smarcel  return MI_CMD_DONE;
184130803Smarcel}
185130803Smarcel
186130803Smarcel/* Add zero or more directories to the front of the source path.  */
187130803Smarcelenum mi_cmd_result
188130803Smarcelmi_cmd_env_dir (char *command, char **argv, int argc)
189130803Smarcel{
190130803Smarcel  int i;
191130803Smarcel  int optind = 0;
192130803Smarcel  int reset = 0;
193130803Smarcel  char *optarg;
194130803Smarcel  enum opt
195130803Smarcel    {
196130803Smarcel      RESET_OPT
197130803Smarcel    };
198130803Smarcel  static struct mi_opt opts[] =
199130803Smarcel  {
200130803Smarcel    {"r", RESET_OPT, 0},
201130803Smarcel    0
202130803Smarcel  };
203130803Smarcel
204130803Smarcel  dont_repeat ();
205130803Smarcel
206130803Smarcel  if (mi_version (uiout) < 2)
207130803Smarcel    {
208130803Smarcel      for (i = argc - 1; i >= 0; --i)
209130803Smarcel	env_execute_cli_command ("dir", argv[i]);
210130803Smarcel      return MI_CMD_DONE;
211130803Smarcel    }
212130803Smarcel
213130803Smarcel  /* Otherwise mi level is 2 or higher.  */
214130803Smarcel  while (1)
215130803Smarcel    {
216130803Smarcel      int opt = mi_getopt ("mi_cmd_env_dir", argc, argv, opts,
217130803Smarcel                           &optind, &optarg);
218130803Smarcel      if (opt < 0)
219130803Smarcel        break;
220130803Smarcel      switch ((enum opt) opt)
221130803Smarcel        {
222130803Smarcel        case RESET_OPT:
223130803Smarcel          reset = 1;
224130803Smarcel          break;
225130803Smarcel        }
226130803Smarcel    }
227130803Smarcel  argv += optind;
228130803Smarcel  argc -= optind;
229130803Smarcel
230130803Smarcel  if (reset)
231130803Smarcel    {
232130803Smarcel      /* Reset means setting to default path first.  */
233130803Smarcel      xfree (source_path);
234130803Smarcel      init_source_path ();
235130803Smarcel    }
236130803Smarcel
237130803Smarcel  for (i = argc - 1; i >= 0; --i)
238130803Smarcel    env_mod_path (argv[i], &source_path);
239130803Smarcel  init_last_source_visited ();
240130803Smarcel
241130803Smarcel  ui_out_field_string (uiout, "source-path", source_path);
242130803Smarcel  forget_cached_source_info ();
243130803Smarcel
244130803Smarcel  return MI_CMD_DONE;
245130803Smarcel}
246130803Smarcel
247130803Smarcelvoid
248130803Smarcel_initialize_mi_cmd_env (void)
249130803Smarcel{
250130803Smarcel  char *env;
251130803Smarcel
252130803Smarcel  /* We want original execution path to reset to, if desired later.  */
253130803Smarcel  env = get_in_environ (inferior_environ, path_var_name);
254130803Smarcel
255130803Smarcel  /* Can be null if path is not set.  */
256130803Smarcel  if (!env)
257130803Smarcel    env = "";
258130803Smarcel  orig_path = xstrdup (env);
259130803Smarcel}
260