xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mi/mi-cmd-env.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* MI Command Set - environment commands.
2    Copyright (C) 2002-2023 Free Software Foundation, Inc.
3 
4    Contributed by Red Hat 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 3 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, see <http://www.gnu.org/licenses/>.  */
20 
21 #include "defs.h"
22 #include "inferior.h"
23 #include "value.h"
24 #include "mi-out.h"
25 #include "mi-cmds.h"
26 #include "mi-getopt.h"
27 #include "symtab.h"
28 #include "target.h"
29 #include "gdbsupport/environ.h"
30 #include "command.h"
31 #include "ui-out.h"
32 #include "top.h"
33 #include <sys/stat.h>
34 #include "source.h"
35 
36 static const char path_var_name[] = "PATH";
37 static char *orig_path = NULL;
38 
39 /* The following is copied from mi-main.c so for m1 and below we can
40    perform old behavior and use cli commands.  If ARGS is non-null,
41    append it to the CMD.  */
42 
43 static void
44 env_execute_cli_command (const char *cmd, const char *args)
45 {
46   if (cmd != 0)
47     {
48       gdb::unique_xmalloc_ptr<char> run;
49 
50       if (args != NULL)
51 	run = xstrprintf ("%s %s", cmd, args);
52       else
53 	run.reset (xstrdup (cmd));
54       execute_command ( /*ui */ run.get (), 0 /*from_tty */ );
55     }
56 }
57 
58 /* Print working directory.  */
59 
60 void
61 mi_cmd_env_pwd (const char *command, char **argv, int argc)
62 {
63   struct ui_out *uiout = current_uiout;
64 
65   if (argc > 0)
66     error (_("-environment-pwd: No arguments allowed"));
67 
68   if (mi_version (uiout) < 2)
69     {
70       env_execute_cli_command ("pwd", NULL);
71       return;
72     }
73 
74   /* Otherwise the mi level is 2 or higher.  */
75 
76   gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
77   if (cwd == NULL)
78     error (_("-environment-pwd: error finding name of working directory: %s"),
79 	   safe_strerror (errno));
80 
81   uiout->field_string ("cwd", cwd.get ());
82 }
83 
84 /* Change working directory.  */
85 
86 void
87 mi_cmd_env_cd (const char *command, char **argv, int argc)
88 {
89   if (argc == 0 || argc > 1)
90     error (_("-environment-cd: Usage DIRECTORY"));
91 
92   env_execute_cli_command ("cd", argv[0]);
93 }
94 
95 static void
96 env_mod_path (const char *dirname, std::string &which_path)
97 {
98   if (dirname == 0 || dirname[0] == '\0')
99     return;
100 
101   /* Call add_path with last arg 0 to indicate not to parse for
102      separator characters.  */
103   add_path (dirname, which_path, 0);
104 }
105 
106 /* Add one or more directories to start of executable search path.  */
107 
108 void
109 mi_cmd_env_path (const char *command, char **argv, int argc)
110 {
111   struct ui_out *uiout = current_uiout;
112   const char *env;
113   int reset = 0;
114   int oind = 0;
115   int i;
116   char *oarg;
117   enum opt
118     {
119       RESET_OPT
120     };
121   static const struct mi_opt opts[] =
122   {
123     {"r", RESET_OPT, 0},
124     { 0, 0, 0 }
125   };
126 
127   dont_repeat ();
128 
129   if (mi_version (uiout) < 2)
130     {
131       for (i = argc - 1; i >= 0; --i)
132 	env_execute_cli_command ("path", argv[i]);
133       return;
134     }
135 
136   /* Otherwise the mi level is 2 or higher.  */
137   while (1)
138     {
139       int opt = mi_getopt ("-environment-path", argc, argv, opts,
140 			   &oind, &oarg);
141 
142       if (opt < 0)
143 	break;
144       switch ((enum opt) opt)
145 	{
146 	case RESET_OPT:
147 	  reset = 1;
148 	  break;
149 	}
150     }
151   argv += oind;
152   argc -= oind;
153 
154   std::string exec_path;
155   if (reset)
156     {
157       /* Reset implies resetting to original path first.  */
158       exec_path = orig_path;
159     }
160   else
161     {
162       /* Otherwise, get current path to modify.  */
163       env = current_inferior ()->environment.get (path_var_name);
164 
165       /* Can be null if path is not set.  */
166       if (!env)
167 	env = "";
168 
169       exec_path = env;
170     }
171 
172   for (i = argc - 1; i >= 0; --i)
173     env_mod_path (argv[i], exec_path);
174 
175   current_inferior ()->environment.set (path_var_name, exec_path.c_str ());
176   env = current_inferior ()->environment.get (path_var_name);
177   uiout->field_string ("path", env);
178 }
179 
180 /* Add zero or more directories to the front of the source path.  */
181 
182 void
183 mi_cmd_env_dir (const char *command, char **argv, int argc)
184 {
185   struct ui_out *uiout = current_uiout;
186   int i;
187   int oind = 0;
188   int reset = 0;
189   char *oarg;
190   enum opt
191     {
192       RESET_OPT
193     };
194   static const struct mi_opt opts[] =
195   {
196     {"r", RESET_OPT, 0},
197     { 0, 0, 0 }
198   };
199 
200   dont_repeat ();
201 
202   if (mi_version (uiout) < 2)
203     {
204       for (i = argc - 1; i >= 0; --i)
205 	env_execute_cli_command ("dir", argv[i]);
206       return;
207     }
208 
209   /* Otherwise mi level is 2 or higher.  */
210   while (1)
211     {
212       int opt = mi_getopt ("-environment-directory", argc, argv, opts,
213 			   &oind, &oarg);
214 
215       if (opt < 0)
216 	break;
217       switch ((enum opt) opt)
218 	{
219 	case RESET_OPT:
220 	  reset = 1;
221 	  break;
222 	}
223     }
224   argv += oind;
225   argc -= oind;
226 
227   if (reset)
228     {
229       /* Reset means setting to default path first.  */
230       init_source_path ();
231     }
232 
233   for (i = argc - 1; i >= 0; --i)
234     env_mod_path (argv[i], source_path);
235 
236   uiout->field_string ("source-path", source_path);
237   forget_cached_source_info ();
238 }
239 
240 /* Set the inferior terminal device name.  */
241 
242 void
243 mi_cmd_inferior_tty_set (const char *command, char **argv, int argc)
244 {
245   if (argc > 0)
246     current_inferior ()->set_tty (argv[0]);
247   else
248     current_inferior ()->set_tty ("");
249 }
250 
251 /* Print the inferior terminal device name.  */
252 
253 void
254 mi_cmd_inferior_tty_show (const char *command, char **argv, int argc)
255 {
256   if ( !mi_valid_noargs ("-inferior-tty-show", argc, argv))
257     error (_("-inferior-tty-show: Usage: No args"));
258 
259   const std::string &inferior_tty = current_inferior ()->tty ();
260   if (!inferior_tty.empty ())
261     current_uiout->field_string ("inferior_tty_terminal", inferior_tty);
262 }
263 
264 void _initialize_mi_cmd_env ();
265 void
266 _initialize_mi_cmd_env ()
267 {
268   const char *env;
269 
270   /* We want original execution path to reset to, if desired later.
271      At this point, current inferior is not created, so cannot use
272      current_inferior ()->environment.  We use getenv here because it
273      is not necessary to create a whole new gdb_environ just for one
274      variable.  */
275   env = getenv (path_var_name);
276 
277   /* Can be null if path is not set.  */
278   if (!env)
279     env = "";
280   orig_path = xstrdup (env);
281 }
282