// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- // Copyright (c) 2001-2007 International Computer Science Institute // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software") // to deal in the Software without restriction, subject to the conditions // listed in the XORP LICENSE file. These conditions include: you must // preserve this copyright notice, and you cannot mention the copyright // holders in advertising related to the Software without their permission. // The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This // notice is a summary of the XORP LICENSE file; the license in that file is // legally binding. #ident "$XORP: xorp/rtrmgr/util.cc,v 1.26 2007/02/16 22:47:27 pavlin Exp $" #include "rtrmgr_module.h" #include "libxorp/xorp.h" #include "libxorp/xlog.h" #include "libxorp/debug.h" #include "libxorp/utility.h" #include "libxorp/utils.hh" #include #include "util.hh" #ifdef HOST_OS_WINDOWS #include #define access(x,y) _access(x,y) #define stat _stat #define S_ISREG _S_ISREG #endif static string s_cfg_root; static string s_bin_root; static string s_boot_file; /** * Find the directory of executable program. * * If the supplied string looks like a qualified path then this * function returns the directory component, otherwise it tries to * locate the named program name in the directories listed in the PATH * environment variable. * Note that in our search we do not consider the XORP root directory. * * @param program_name the name of the program to find. * * @return directory name of executable program on success, empty string * on failure. */ static string find_executable_program_dir(const string& program_name) { debug_msg("%s\n", program_name.c_str()); if (program_name.size() >= MAXPATHLEN) return string(""); // Error: invalid program name // // Look for trailing slash in program_name // string::size_type slash = program_name.rfind(PATH_DELIMITER_CHAR); if (slash != string::npos) { string path = program_name.substr(0, slash); return path; } // // Go through the PATH environment variable and find the program location // string slash_progname(PATH_DELIMITER_STRING); slash_progname += program_name; slash_progname += EXECUTABLE_SUFFIX; const char* s = getenv("PATH"); while (s != NULL && *s != '\0') { const char* e = strchr(s, PATH_ENV_DELIMITER_CHAR); string path; if (e != NULL) { path = string(s, e); s = e + 1; } else { path = string(s); s = NULL; } string complete_path = path + slash_progname; if (access(complete_path.c_str(), X_OK) == 0) { return path; } } return string(""); // Error: nothing found } static string xorp_real_path(const string& path) { debug_msg("path: %s\n", path.c_str()); char rp[MAXPATHLEN]; #ifdef HOST_OS_WINDOWS char *fp = NULL; if (GetFullPathNameA(path.c_str(), sizeof(rp), rp, &fp) > 0) { debug_msg("return %s\n", rp); return string(rp); } #else const char* prp = realpath(path.c_str(), rp); if (prp != NULL) { debug_msg("return %s\n", prp); return string(prp); } #endif // XLOG_WARNING("realpath(%s) failed.", path.c_str()); debug_msg("return %s\n", path.c_str()); return path; } void xorp_path_init(const char* argv0) { const char* xr = getenv("XORP_ROOT"); if (xr != NULL) { s_bin_root = xr; s_cfg_root = xr; s_boot_file = s_cfg_root + "/rtrmgr/config.boot"; return; } string current_root = find_executable_program_dir(argv0) + PATH_DELIMITER_STRING + PATH_PARENT; current_root = xorp_real_path(current_root); debug_msg("current_root: %s\n", current_root.c_str()); string build_root = xorp_real_path(XORP_BUILD_ROOT); debug_msg("build_root: %s\n", build_root.c_str()); if (current_root == build_root) { s_bin_root = build_root; s_cfg_root = xorp_real_path(XORP_SRC_ROOT); s_boot_file = s_cfg_root + "/rtrmgr/config.boot"; debug_msg("s_bin_root: %s\n", s_bin_root.c_str()); debug_msg("s_cfg_root: %s\n", s_cfg_root.c_str()); debug_msg("s_boot_file: %s\n", s_boot_file.c_str()); return; } string install_root = xorp_real_path(XORP_INSTALL_ROOT); s_bin_root = install_root; s_cfg_root = install_root; s_boot_file = s_cfg_root + "/config.boot"; debug_msg("s_bin_root: %s\n", s_bin_root.c_str()); debug_msg("s_cfg_root: %s\n", s_cfg_root.c_str()); debug_msg("s_boot_file: %s\n", s_boot_file.c_str()); } const string& xorp_binary_root_dir() { return s_bin_root; } const string& xorp_config_root_dir() { return s_cfg_root; } string xorp_template_dir() { return s_cfg_root + string("/etc/templates"); } string xorp_xrl_targets_dir() { return s_cfg_root + string("/xrl/targets"); } string xorp_boot_file() { return s_boot_file; } string& unquote(string& s) { if (s.length() >= 2 && s[0] == '"' && s[s.size() - 1] == '"') { s = s.substr(1, s.size() - 2); } return s; } string unquote(const string& s) { if (s.length() >= 2 && s[0] == '"' && s[s.size() - 1] == '"') { return s.substr(1, s.size() - 2); } return s; } bool is_quotable_string(const string& s) { size_t i; for (i = 0; i < s.size(); i++) { if (! xorp_isalnum(s[i])) return (true); } return (false); } string find_executable_filename(const string& program_filename) { string executable_filename; struct stat statbuf; if (program_filename.size() == 0) { return string(""); // Error } // Assume the path passed to us is a UNIX-style path. executable_filename = unix_path_to_native(program_filename); // // TODO: take care of the commented-out access() calls below (by BMS). // // Comment out the access() calls for now -- xorpsh does not // like them, when running under sudo -u xorp (euid?) and // as a result xorpsh fails to start up. // Consider checking for it in configure.in and shipping // our own if we can't find it on the system. // if (is_absolute_path(executable_filename)) { // Absolute path name if (stat(executable_filename.c_str(), &statbuf) == 0 && // access(executable_filename.c_str(), X_OK) == 0 && S_ISREG(statbuf.st_mode)) { return executable_filename; } return string(""); // Error } // Relative path name string xorp_root_dir = xorp_binary_root_dir(); list path; path.push_back(xorp_root_dir); // Expand path const char* p = getenv("PATH"); if (p != NULL) { list l2 = split(p, PATH_ENV_DELIMITER_CHAR); path.splice(path.end(), l2); } // Search each path component while (!path.empty()) { // Don't forget to append the executable suffix if needed. string full_path_executable = path.front() + PATH_DELIMITER_STRING + executable_filename + EXECUTABLE_SUFFIX; #ifdef HOST_OS_WINDOWS // Deal with any silly tricks which MSYS may have pulled on // us, like using UNIX-style slashes in a DOS-style path. Grr. -bms full_path_executable = unix_path_to_native(full_path_executable); #endif if (stat(full_path_executable.c_str(), &statbuf) == 0 && // access(program_filename.c_str(), X_OK) == 0 && S_ISREG(statbuf.st_mode)) { executable_filename = full_path_executable; return executable_filename; } path.pop_front(); } return string(""); // Error } void find_executable_filename_and_arguments(const string& program_request, string& executable_filename, string& program_arguments) { executable_filename = strip_empty_spaces(program_request); program_arguments = ""; string::size_type space; space = executable_filename.find(' '); if (space == string::npos) space = executable_filename.find('\t'); if (space != string::npos) { program_arguments = executable_filename.substr(space + 1); executable_filename = executable_filename.substr(0, space); } executable_filename = find_executable_filename(executable_filename); if (executable_filename.empty()) program_arguments = ""; }