1 /* MI Command Set - environment commands. 2 3 Copyright (C) 2002-2004, 2007-2012 Free Software Foundation, Inc. 4 5 Contributed by Red Hat Inc. 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 #include "defs.h" 23 #include "inferior.h" 24 #include "value.h" 25 #include "mi-out.h" 26 #include "mi-cmds.h" 27 #include "mi-getopt.h" 28 #include "symtab.h" 29 #include "target.h" 30 #include "environ.h" 31 #include "command.h" 32 #include "ui-out.h" 33 #include "top.h" 34 35 #include "gdb_string.h" 36 #include "gdb_stat.h" 37 38 static void env_mod_path (char *dirname, char **which_path); 39 extern void _initialize_mi_cmd_env (void); 40 41 static const char path_var_name[] = "PATH"; 42 static char *orig_path = NULL; 43 44 /* The following is copied from mi-main.c so for m1 and below we can 45 perform old behavior and use cli commands. If ARGS is non-null, 46 append it to the CMD. */ 47 static void 48 env_execute_cli_command (const char *cmd, const char *args) 49 { 50 if (cmd != 0) 51 { 52 struct cleanup *old_cleanups; 53 char *run; 54 55 if (args != NULL) 56 run = xstrprintf ("%s %s", cmd, args); 57 else 58 run = xstrdup (cmd); 59 old_cleanups = make_cleanup (xfree, run); 60 execute_command ( /*ui */ run, 0 /*from_tty */ ); 61 do_cleanups (old_cleanups); 62 return; 63 } 64 } 65 66 67 /* Print working directory. */ 68 void 69 mi_cmd_env_pwd (char *command, char **argv, int argc) 70 { 71 struct ui_out *uiout = current_uiout; 72 73 if (argc > 0) 74 error (_("-environment-pwd: No arguments required")); 75 76 if (mi_version (uiout) < 2) 77 { 78 env_execute_cli_command ("pwd", NULL); 79 return; 80 } 81 82 /* Otherwise the mi level is 2 or higher. */ 83 84 if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf))) 85 error (_("-environment-pwd: error finding name of working directory: %s"), 86 safe_strerror (errno)); 87 88 ui_out_field_string (uiout, "cwd", gdb_dirbuf); 89 } 90 91 /* Change working directory. */ 92 void 93 mi_cmd_env_cd (char *command, char **argv, int argc) 94 { 95 if (argc == 0 || argc > 1) 96 error (_("-environment-cd: Usage DIRECTORY")); 97 98 env_execute_cli_command ("cd", argv[0]); 99 } 100 101 static void 102 env_mod_path (char *dirname, char **which_path) 103 { 104 if (dirname == 0 || dirname[0] == '\0') 105 return; 106 107 /* Call add_path with last arg 0 to indicate not to parse for 108 separator characters. */ 109 add_path (dirname, which_path, 0); 110 } 111 112 /* Add one or more directories to start of executable search path. */ 113 void 114 mi_cmd_env_path (char *command, char **argv, int argc) 115 { 116 struct ui_out *uiout = current_uiout; 117 char *exec_path; 118 char *env; 119 int reset = 0; 120 int optind = 0; 121 int i; 122 char *optarg; 123 enum opt 124 { 125 RESET_OPT 126 }; 127 static const struct mi_opt opts[] = 128 { 129 {"r", RESET_OPT, 0}, 130 { 0, 0, 0 } 131 }; 132 133 dont_repeat (); 134 135 if (mi_version (uiout) < 2) 136 { 137 for (i = argc - 1; i >= 0; --i) 138 env_execute_cli_command ("path", argv[i]); 139 return; 140 } 141 142 /* Otherwise the mi level is 2 or higher. */ 143 while (1) 144 { 145 int opt = mi_getopt ("-environment-path", argc, argv, opts, 146 &optind, &optarg); 147 148 if (opt < 0) 149 break; 150 switch ((enum opt) opt) 151 { 152 case RESET_OPT: 153 reset = 1; 154 break; 155 } 156 } 157 argv += optind; 158 argc -= optind; 159 160 161 if (reset) 162 { 163 /* Reset implies resetting to original path first. */ 164 exec_path = xstrdup (orig_path); 165 } 166 else 167 { 168 /* Otherwise, get current path to modify. */ 169 env = get_in_environ (current_inferior ()->environment, path_var_name); 170 171 /* Can be null if path is not set. */ 172 if (!env) 173 env = ""; 174 exec_path = xstrdup (env); 175 } 176 177 for (i = argc - 1; i >= 0; --i) 178 env_mod_path (argv[i], &exec_path); 179 180 set_in_environ (current_inferior ()->environment, path_var_name, exec_path); 181 xfree (exec_path); 182 env = get_in_environ (current_inferior ()->environment, path_var_name); 183 ui_out_field_string (uiout, "path", env); 184 } 185 186 /* Add zero or more directories to the front of the source path. */ 187 void 188 mi_cmd_env_dir (char *command, char **argv, int argc) 189 { 190 struct ui_out *uiout = current_uiout; 191 int i; 192 int optind = 0; 193 int reset = 0; 194 char *optarg; 195 enum opt 196 { 197 RESET_OPT 198 }; 199 static const struct mi_opt opts[] = 200 { 201 {"r", RESET_OPT, 0}, 202 { 0, 0, 0 } 203 }; 204 205 dont_repeat (); 206 207 if (mi_version (uiout) < 2) 208 { 209 for (i = argc - 1; i >= 0; --i) 210 env_execute_cli_command ("dir", argv[i]); 211 return; 212 } 213 214 /* Otherwise mi level is 2 or higher. */ 215 while (1) 216 { 217 int opt = mi_getopt ("-environment-directory", argc, argv, opts, 218 &optind, &optarg); 219 220 if (opt < 0) 221 break; 222 switch ((enum opt) opt) 223 { 224 case RESET_OPT: 225 reset = 1; 226 break; 227 } 228 } 229 argv += optind; 230 argc -= optind; 231 232 if (reset) 233 { 234 /* Reset means setting to default path first. */ 235 xfree (source_path); 236 init_source_path (); 237 } 238 239 for (i = argc - 1; i >= 0; --i) 240 env_mod_path (argv[i], &source_path); 241 242 ui_out_field_string (uiout, "source-path", source_path); 243 forget_cached_source_info (); 244 } 245 246 /* Set the inferior terminal device name. */ 247 void 248 mi_cmd_inferior_tty_set (char *command, char **argv, int argc) 249 { 250 set_inferior_io_terminal (argv[0]); 251 } 252 253 /* Print the inferior terminal device name */ 254 void 255 mi_cmd_inferior_tty_show (char *command, char **argv, int argc) 256 { 257 const char *inferior_io_terminal = get_inferior_io_terminal (); 258 259 if ( !mi_valid_noargs ("-inferior-tty-show", argc, argv)) 260 error (_("-inferior-tty-show: Usage: No args")); 261 262 if (inferior_io_terminal) 263 ui_out_field_string (current_uiout, 264 "inferior_tty_terminal", inferior_io_terminal); 265 } 266 267 void 268 _initialize_mi_cmd_env (void) 269 { 270 struct gdb_environ *environment; 271 char *env; 272 273 /* We want original execution path to reset to, if desired later. 274 At this point, current inferior is not created, so cannot use 275 current_inferior ()->environment. Also, there's no obvious 276 place where this code can be moved suchs that it surely run 277 before any code possibly mangles original PATH. */ 278 environment = make_environ (); 279 init_environ (environment); 280 env = get_in_environ (environment, path_var_name); 281 282 /* Can be null if path is not set. */ 283 if (!env) 284 env = ""; 285 orig_path = xstrdup (env); 286 free_environ (environment); 287 } 288