24#include "gdbsupport/gdb_regex.h"
35#include "readline/tilde.h"
39#include "gdbsupport/filestuff.h"
41#include "gdb/section-scripts.h"
43#include "gdbsupport/pathstuff.h"
52#define AUTO_SECTION_NAME ".debug_gdb_scripts"
55#define DEBUGLINK_SECTION_NAME ".gnu_debuglink"
60 const char *section_name,
unsigned offset);
65 const char *section_name,
unsigned offset);
77 gdb_printf (file, _(
"Debugging output for files "
78 "of 'set auto-load ...' is %s.\n"),
95 gdb_printf (file, _(
"Auto-loading of canned sequences of commands "
135 gdb_printf (file, _(
"Auto-loading of .gdbinit script from current "
136 "directory is %s.\n"),
161 gdb_printf (file, _(
"List of directories from which to load "
162 "auto-loaded scripts is %s.\n"),
179static std::vector<gdb::unique_xmalloc_ptr<char>>
182 char *s = xstrdup (
string);
189 std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec
190 = dirnames_to_char_ptr_vec (s);
210 for (
size_t i = 0; i < len; i++)
213 gdb::unique_xmalloc_ptr<char> expanded (tilde_expand (in_vec.get ()));
214 gdb::unique_xmalloc_ptr<char> real_path = gdb_realpath (expanded.get ());
218 gdb::unique_xmalloc_ptr<char> original = std::move (in_vec);
219 in_vec = std::move (expanded);
223 if (strcmp (in_vec.get (), original.get ()) == 0)
228 original.get (), in_vec.get ());
232 if (strcmp (real_path.get (), in_vec.get ()) != 0)
275 for (cs =
value; *cs && (*cs == DIRNAME_SEPARATOR || IS_DIR_SEPARATOR (*cs));
278 gdb_printf (file, _(
"Auto-load files are safe to load from any "
281 gdb_printf (file, _(
"List of directories from which it is safe to "
282 "auto-load files is %s.\n"),
292 if (args == NULL || *args == 0)
294Directory argument required.\n\
295Use 'set auto-load safe-path /' for disabling the auto-load safe-path security.\
299 DIRNAME_SEPARATOR, args);
310 if (args == NULL || *args == 0)
311 error (_(
"Directory argument required."));
314 DIRNAME_SEPARATOR, args);
323 size_t pattern_len = strlen (pattern);
324 size_t filename_len = strlen (filename);
332 while (pattern_len && IS_DIR_SEPARATOR (pattern[pattern_len - 1]))
334 pattern[pattern_len] =
'\0';
339 if (pattern_len == 0)
349 while (filename_len && IS_DIR_SEPARATOR (filename[filename_len - 1]))
351 filename[filename_len] =
'\0';
352 if (filename_len == 0)
367 while (filename_len > 0 && !IS_DIR_SEPARATOR (filename[filename_len - 1]))
376static ATTRIBUTE_PURE
int
379 char *filename_copy, *pattern_copy;
381 filename_copy = (
char *) alloca (strlen (filename) + 1);
382 strcpy (filename_copy, filename);
383 pattern_copy = (
char *) alloca (strlen (pattern) + 1);
384 strcpy (pattern_copy, pattern);
396 gdb::unique_xmalloc_ptr<char> *filename_realp)
398 const char *pattern = NULL;
409 if (*filename_realp == NULL)
411 *filename_realp = gdb_realpath (filename);
414 filename, filename_realp->get ());
417 if (strcmp (filename_realp->get (), filename) != 0)
441 gdb::unique_xmalloc_ptr<char> filename_real;
442 static bool advice_printed =
false;
451 warning (_(
"File \"%ps\" auto-loading has been declined by your "
452 "`auto-load safe-path' set to \"%s\"."),
460 std::string home_config = find_gdb_home_config_file (
GDBINIT, &buf);
461 if (home_config.empty ())
465 std::string config_dir_file
466 = get_standard_config_filename (
GDBINIT);
467 if (!config_dir_file.empty ())
468 home_config = config_dir_file;
471 const char *homedir = getenv (
"HOME");
472 if (homedir ==
nullptr)
474 home_config = (std::string (homedir) + SLASH_STRING
480To enable execution of this file add\n\
481\tadd-auto-load-safe-path %s\n\
482line to your configuration file \"%ps\".\n\
483To completely disable this security protection add\n\
484\tset auto-load safe-path /\n\
485line to your configuration file \"%ps\".\n\
486For more information about this security protection see the\n\
487\"Auto-loading safe path\" section in the GDB manual. E.g., run from the shell:\n\
488\tinfo \"(gdb)Auto-loading safe path\"\n"),
489 filename_real.get (),
491 home_config.c_str ()),
493 home_config.c_str ()));
494 advice_printed =
true;
564 return htab_hash_string (e->
name) ^ htab_hash_pointer (e->
language);
612 if (info->loaded_script_files == NULL)
627 const char *
name,
const char *full_path,
635 slot = (
struct loaded_script **) htab_find_slot (htab, &entry, INSERT);
636 bool in_hash_table = *slot != NULL;
649 p = ((
char*) *slot) +
sizeof (**slot);
656 (*slot)->full_path = p;
659 (*slot)->full_path = NULL;
664 return in_hash_table;
683 slot = (
struct loaded_script **) htab_find_slot (htab, &entry, INSERT);
684 bool in_hash_table = *slot != NULL;
695 p = ((
char*) *slot) +
sizeof (**slot);
698 (*slot)->full_path = NULL;
703 return in_hash_table;
715 if (info != NULL && info->loaded_script_files != NULL)
727 const char *debugfile;
731 std::string filename = std::string (realname) + suffix;
733 gdb_file_up input = gdb_fopen_cloexec (filename.c_str (),
"r");
734 debugfile = filename.c_str ();
738 input !=
nullptr ?
"exists" :
"does not exist");
740 std::string debugfile_holder;
746 std::vector<gdb::unique_xmalloc_ptr<char>> vec
750 (
"Searching 'set auto-load scripts-directory' path \"%s\".",
754 if (HAS_DRIVE_SPEC (debugfile))
755 filename = (std::string(
"\\") + debugfile[0]
756 + STRIP_DRIVE_SPEC (debugfile));
758 for (
const gdb::unique_xmalloc_ptr<char> &dir : vec)
761 debugfile_holder = dir.get () + filename;
762 debugfile = debugfile_holder.c_str ();
764 input = gdb_fopen_cloexec (debugfile,
"r");
771 :
"does not exist"));
783 (
"Loading %s script \"%s\" by extension for objfile \"%s\".",
808 gdb_assert (sourcer != NULL);
827 gdb::unique_xmalloc_ptr<char> realname
836 size_t len = strlen (realname.get ());
837 const size_t lexe =
sizeof (
".exe") - 1;
839 if (len > lexe && strcasecmp (realname.get () + len - lexe,
".exe") == 0)
842 realname.get ()[len] =
'\0';
845 (
"Stripped .exe suffix, retrying with \"%s\".", realname.get ());
857 if (parent !=
nullptr)
860 gdb::unique_xmalloc_ptr<char> debuglink
861 (bfd_get_debug_link_info (parent->
obfd.get (), &crc32));
863 if (debuglink.get () !=
nullptr
864 && strcmp (debuglink.get (), lbasename (realname.get ())) != 0)
869 std::string p_realname = gdb_realpath (
objfile_name (parent)).get ();
870 size_t last = p_realname.find_last_of (
'/');
872 if (last != std::string::npos)
874 p_realname.replace (last + 1, std::string::npos,
878 (
"Debug filename mismatch, retrying with \"%s\".",
879 p_realname.c_str ());
896 const char *section_name,
unsigned int offset,
907 section_name, offset);
926 (
"Loading %s script \"%s\" from section \"%s\" of objfile \"%s\".",
944 section_name, offset);
949 (opened ? opened->full_path.get (): NULL),
953 if (opened && !in_hash_table)
955 opened->full_path.get ());
966 const char *section_name,
unsigned int offset,
970 const char *newline, *script_text;
976 newline = strchr (script,
'\n');
977 std::string name_holder;
983 name_holder = std::string (script, newline - script);
984 buf = name_holder.c_str ();
985 for (p = buf; *p !=
'\0'; ++p)
991 if (p != buf && *p ==
'\0')
998Missing/bad script name in entry at offset %u in section %s\n\
1000 offset, section_name,
1005 script_text = newline + 1;
1009 if (executor == NULL)
1013 section_name, offset);
1026 (
"Loading %s script \"%s\" from section \"%s\" of objfile \"%s\".",
1035 if (is_safe && !in_hash_table)
1053 const char *start,
const char *end)
1060 for (p = start; p < end; ++p)
1064 unsigned int offset = p - start;
1069 case SECTION_SCRIPT_ID_PYTHON_FILE:
1070 case SECTION_SCRIPT_ID_PYTHON_TEXT:
1073 case SECTION_SCRIPT_ID_SCHEME_FILE:
1074 case SECTION_SCRIPT_ID_SCHEME_TEXT:
1078 warning (_(
"Invalid entry in %s section"), section_name);
1085 while (p < end && *p !=
'\0')
1089 warning (_(
"Non-nul-terminated entry in %s at offset %u"),
1090 section_name, offset);
1097 case SECTION_SCRIPT_ID_PYTHON_FILE:
1098 case SECTION_SCRIPT_ID_SCHEME_FILE:
1101 warning (_(
"Empty entry in %s at offset %u"),
1102 section_name, offset);
1106 section_name, offset, entry);
1108 case SECTION_SCRIPT_ID_PYTHON_TEXT:
1109 case SECTION_SCRIPT_ID_SCHEME_TEXT:
1111 section_name, offset, entry);
1123 asection *scripts_sect;
1124 bfd_byte *data = NULL;
1126 scripts_sect = bfd_get_section_by_name (abfd, section_name);
1127 if (scripts_sect == NULL
1128 || (bfd_section_flags (scripts_sect) & SEC_HAS_CONTENTS) == 0)
1131 if (!bfd_get_full_section_contents (abfd, scripts_sect, &data))
1132 warning (_(
"Couldn't read %s section of %ps"),
1135 bfd_get_filename (abfd)));
1138 gdb::unique_xmalloc_ptr<bfd_byte> data_holder (data);
1140 char *p = (
char *) data;
1142 p + bfd_section_size (scripts_sect));
1210 if (script->
language == data->language && re_exec (script->
name))
1211 data->scripts_p->push_back (script);
1233 uiout->
text (
"\tfull name: ");
1244 return FILENAME_CMP (a->
name, b->
name) < 0;
1277 if (pattern && *pattern)
1279 char *re_err =
re_comp (pattern);
1282 error (_(
"Invalid regexp: %s"), re_err);
1293 std::vector<loaded_script *> script_files, script_texts;
1303 std::sort (script_files.begin (), script_files.end (),
1315 std::sort (script_texts.begin (), script_texts.end (),
1319 int nr_scripts = script_files.size () + script_texts.size ();
1328 "AutoLoadedScriptsTable");
1338 if (nr_scripts == 0)
1340 if (pattern && *pattern)
1341 uiout->
message (
"No auto-load scripts matching %s.\n", pattern);
1343 uiout->
message (
"No auto-load scripts.\n");
1361 gdb_printf (_(
"Local .gdbinit file was not found.\n"));
1363 gdb_printf (_(
"Local .gdbinit file \"%ps\" has been loaded.\n"),
1367 gdb_printf (_(
"Local .gdbinit file \"%ps\" has not been loaded.\n"),
1380 const char *section_name,
unsigned offset)
1385Unsupported auto-load script at offset %u in section %s\n\
1387Use `info auto-load %s-scripts [REGEXP]' to list them."),
1388 offset, section_name,
1404 const char *section_name,
unsigned offset)
1409Missing auto-load script at offset %u in section %s\n\
1411Use `info auto-load %s-scripts [REGEXP]' to list them."),
1412 offset, section_name,
1430 length = args ? strlen (args) : 0;
1432 while (length > 0 && (args[length - 1] ==
' ' || args[length - 1] ==
'\t'))
1435 if (length == 0 || (strncmp (args,
"off", length) != 0
1436 && strncmp (args,
"0", length) != 0
1437 && strncmp (args,
"no", length) != 0
1438 && strncmp (args,
"disable", length) != 0))
1439 error (_(
"Valid is only global 'set auto-load no'; "
1440 "otherwise check the auto-load sub-commands."));
1459Auto-loading specific settings.\n\
1460Configure various auto-load-specific variables such as\n\
1461automatic loading of Python scripts."),
1476Show auto-loading specific settings.\n\
1477Show configuration of various auto-load-specific variables such as\n\
1478automatic loading of Python scripts."),
1518Print current status of auto-loaded files.\n\
1519Print whether various files like Python scripts or .gdbinit files have been\n\
1520found and/or loaded."),
1535 gdb::unique_xmalloc_ptr<char> scripts_directory_help, gdb_name_help,
1536 python_name_help, guile_name_help;
1544Enable or disable auto-loading of canned sequences of commands scripts."), _(
"\
1545Show whether auto-loading of canned sequences of commands scripts is enabled."),
1547If enabled, canned sequences of commands are loaded when the debugger reads\n\
1548an executable or shared library.\n\
1549This option has security implications for untrusted inferiors."),
1555 _(
"Print the list of automatically loaded sequences of commands.\n\
1556Usage: info auto-load gdb-scripts [REGEXP]"),
1561Enable or disable auto-loading of .gdbinit script in current directory."), _(
"\
1562Show whether auto-loading .gdbinit script in current directory is enabled."),
1564If enabled, canned sequences of commands are loaded when debugger starts\n\
1565from .gdbinit file in current directory. Such files are deprecated,\n\
1566use a script associated with inferior executable file instead.\n\
1567This option has security implications for untrusted inferiors."),
1573 _(
"Print whether current directory .gdbinit file has been loaded.\n\
1574Usage: info auto-load local-gdbinit"),
1580GDB scripts: OBJFILE%s\n"),
1582 python_name_help = NULL;
1587Python scripts: OBJFILE%s\n"),
1590 guile_name_help = NULL;
1595Guile scripts: OBJFILE%s\n"),
1598 scripts_directory_help
1600Automatically loaded scripts are located in one of the directories listed\n\
1606This option is ignored for the kinds of scripts \
1607having 'set auto-load ... off'.\n\
1608Directories listed here need to be present also \
1609in the 'set auto-load safe-path'\n\
1611 gdb_name_help.get (),
1612 python_name_help.get () ? python_name_help.get () :
"",
1613 guile_name_help.get () ? guile_name_help.get () :
"");
1617Set the list of directories from which to load auto-loaded scripts."), _(
"\
1618Show the list of directories from which to load auto-loaded scripts."),
1619 scripts_directory_help.get (),
1626Set the list of files and directories that are safe for auto-loading."), _(
"\
1627Show the list of files and directories that are safe for auto-loading."), _(
"\
1628Various files loaded automatically for the 'set auto-load ...' options must\n\
1629be located in one of the directories listed by this option. Warning will be\n\
1630printed and file will not be used otherwise.\n\
1631You can mix both directory and filename entries.\n\
1632Setting this parameter to an empty list resets it to its default value.\n\
1633Setting this parameter to '/' (without the quotes) allows any file\n\
1634for the 'set auto-load ...' options. Each path entry can be also shell\n\
1635wildcard pattern; '*' does not match directory separator.\n\
1636This option is ignored for the kinds of files having 'set auto-load ... off'.\n\
1637This option has security implications for untrusted inferiors."),
1647 _(
"Add entries to the list of directories from which it is safe "
1648 "to auto-load files.\n\
1649See the commands 'set auto-load safe-path' and 'show auto-load safe-path' to\n\
1650access the current full list setting."),
1656 _(
"Add entries to the list of directories from which to load "
1657 "auto-loaded scripts.\n\
1658See the commands 'set auto-load scripts-directory' and\n\
1659'show auto-load scripts-directory' to access the current full list setting."),
1665Set auto-load verifications debugging."), _(
"\
1666Show auto-load verifications debugging."), _(
"\
1667When non-zero, debugging output for files of 'set auto-load ...'\n\
static void add_auto_load_safe_path(const char *args, int from_tty)
static int filename_is_in_auto_load_safe_path_vec(const char *filename, gdb::unique_xmalloc_ptr< char > *filename_realp)
struct auto_load_pspace_info * get_auto_load_pspace_data_for_loading(struct program_space *pspace)
static void add_auto_load_dir(const char *args, int from_tty)
#define AUTO_SECTION_NAME
static std::string auto_load_dir
static int eq_loaded_script_entry(const void *a, const void *b)
static hashval_t hash_loaded_script_entry(const void *data)
static int filename_is_in_pattern_1(char *filename, char *pattern)
static void info_auto_load_cmd(const char *args, int from_tty)
static void show_debug_auto_load(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
static void show_auto_load_dir(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
static void auto_load_section_scripts(struct objfile *objfile, const char *section_name)
bool file_is_auto_load_safe(const char *filename)
static struct auto_load_pspace_info * get_auto_load_pspace_data(struct program_space *pspace)
static void auto_load_new_objfile(struct objfile *objfile)
static void execute_script_contents(struct auto_load_pspace_info *pspace_info, struct objfile *objfile, const struct extension_language_defn *language, const char *section_name, unsigned int offset, const char *script)
void _initialize_auto_load()
bool auto_load_gdb_scripts_enabled(const struct extension_language_defn *extlang)
struct cmd_list_element ** auto_load_info_cmdlist_get(void)
static void show_auto_load_gdb_scripts(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
static void info_auto_load_gdb_scripts(const char *pattern, int from_tty)
static void set_auto_load_safe_path(const char *args, int from_tty, struct cmd_list_element *c)
void load_auto_scripts_for_objfile(struct objfile *objfile)
static ATTRIBUTE_PURE int filename_is_in_pattern(const char *filename, const char *pattern)
bool auto_load_local_gdbinit_loaded
static void print_scripts(const std::vector< loaded_script * > &scripts)
static void init_loaded_scripts_info(struct auto_load_pspace_info *pspace_info)
static bool maybe_add_script_file(struct auto_load_pspace_info *pspace_info, bool loaded, const char *name, const char *full_path, const struct extension_language_defn *language)
static int auto_load_objfile_script_1(struct objfile *objfile, const char *realname, const struct extension_language_defn *language)
static void print_script(struct loaded_script *script)
char auto_load_info_scripts_pattern_nl[]
static void show_auto_load_local_gdbinit(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
static void set_auto_load_dir(const char *args, int from_tty, struct cmd_list_element *c)
static std::vector< gdb::unique_xmalloc_ptr< char > > auto_load_expand_dir_vars(const char *string)
static void set_auto_load_cmd(const char *args, int from_tty)
static void source_script_file(struct auto_load_pspace_info *pspace_info, struct objfile *objfile, const struct extension_language_defn *language, const char *section_name, unsigned int offset, const char *file)
bool auto_load_local_gdbinit
void auto_load_info_scripts(const char *pattern, int from_tty, const struct extension_language_defn *language)
static std::string auto_load_safe_path
static void clear_section_scripts(void)
static const registry< program_space >::key< auto_load_pspace_info > auto_load_pspace_data
struct cmd_list_element ** auto_load_set_cmdlist_get(void)
static std::vector< gdb::unique_xmalloc_ptr< char > > auto_load_safe_path_vec
static void maybe_print_unsupported_script_warning(struct auto_load_pspace_info *, struct objfile *objfile, const struct extension_language_defn *language, const char *section_name, unsigned offset)
static void source_section_scripts(struct objfile *objfile, const char *section_name, const char *start, const char *end)
static void show_auto_load_safe_path(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
static bool sort_scripts_by_name(loaded_script *a, loaded_script *b)
static void auto_load_gdb_datadir_changed(void)
static bool maybe_add_script_text(struct auto_load_pspace_info *pspace_info, bool loaded, const char *name, const struct extension_language_defn *language)
char * auto_load_local_gdbinit_pathname
static void info_auto_load_local_gdbinit(const char *args, int from_tty)
struct cmd_list_element ** auto_load_show_cmdlist_get(void)
gdb::observers::token auto_load_new_objfile_observer_token
static int collect_matching_scripts(void **slot, void *info)
static void maybe_print_script_not_found_warning(struct auto_load_pspace_info *, struct objfile *objfile, const struct extension_language_defn *language, const char *section_name, unsigned offset)
static bool auto_load_gdb_scripts
static void auto_load_safe_path_vec_update(void)
void auto_load_objfile_script(struct objfile *objfile, const struct extension_language_defn *language)
#define auto_load_debug_printf(fmt,...)
ui_file_style style() const
void field_string(const char *fldname, const char *string, const ui_file_style &style=ui_file_style())
void text(const char *string)
void table_header(int width, ui_align align, const std::string &col_name, const std::string &col_hdr)
void message(const char *format,...) ATTRIBUTE_PRINTF(2
struct cmd_list_element * showlist
struct cmd_list_element * infolist
struct cmd_list_element * cmdlist
struct cmd_list_element * setlist
struct cmd_list_element * showdebuglist
gdb::optional< open_script > find_and_open_script(const char *script_file, int search_path)
struct cmd_list_element * setdebuglist
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
set_show_commands add_setshow_optional_filename_cmd(const char *name, enum command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
void set_cmd_completer(struct cmd_list_element *cmd, completer_ftype *completer)
struct cmd_list_element * add_show_prefix_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **subcommands, int allow_unknown, struct cmd_list_element **list)
void cmd_func(struct cmd_list_element *cmd, const char *args, int from_tty)
struct cmd_list_element * add_prefix_cmd(const char *name, enum command_class theclass, cmd_simple_func_ftype *fun, const char *doc, struct cmd_list_element **subcommands, int allow_unknown, struct cmd_list_element **list)
set_show_commands add_setshow_boolean_cmd(const char *name, enum command_class theclass, bool *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
void do_set_command(const char *arg, int from_tty, struct cmd_list_element *c)
cli_style_option file_name_style
void filename_completer(struct cmd_list_element *ignore, completion_tracker &tracker, const char *text, const char *word)
#define AUTO_LOAD_SAFE_PATH
std::string debug_file_directory
EXTERN_C char * re_comp(const char *)
objfile_script_sourcer_func * ext_lang_objfile_script_sourcer(const struct extension_language_defn *extlang)
const char * ext_lang_name(const struct extension_language_defn *extlang)
bool ext_lang_auto_load_enabled(const struct extension_language_defn *extlang)
const struct extension_language_defn extension_language_gdb
const struct extension_language_defn * get_ext_lang_defn(enum extension_language lang)
void auto_load_ext_lang_scripts_for_objfile(struct objfile *objfile)
const char * ext_lang_auto_load_suffix(const struct extension_language_defn *extlang)
objfile_script_executor_func * ext_lang_objfile_script_executor(const struct extension_language_defn *extlang)
void objfile_script_sourcer_func(const struct extension_language_defn *, struct objfile *, FILE *stream, const char *filename)
void objfile_script_executor_func(const struct extension_language_defn *, struct objfile *, const char *name, const char *script)
int is_target_filename(const char *name)
observable< struct objfile * > new_objfile
observable gdb_datadir_changed
const char * objfile_name(const struct objfile *objfile)
struct program_space * current_program_space
htab_up loaded_script_files
htab_up loaded_script_texts
bool script_not_found_warning_printed
bool unsupported_script_warning_printed
gdb::optional< setting > var
__extension__ enum cmd_types type
struct cmd_list_element * next
const struct extension_language_defn * language
std::vector< loaded_script * > * scripts_p
collect_matching_scripts_data(std::vector< loaded_script * > *scripts_p_, const extension_language_defn *language_)
const struct extension_language_defn * language
const char * original_name
struct objfile * separate_debug_objfile_backlink
static styled_string_s * styled_string(const ui_file_style &style, const char *str, styled_string_s &&tmp={})
int gdb_filename_fnmatch(const char *pattern, const char *string, int flags)
void gdb_printf(struct ui_file *stream, const char *format,...)
void substitute_path_component(char **stringp, const char *from, const char *to)