summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--main.cxx25
-rw-r--r--tapsets.cxx120
-rw-r--r--util.cxx27
4 files changed, 86 insertions, 94 deletions
diff --git a/ChangeLog b/ChangeLog
index 47b52f17..b312bc34 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2008-08-09 Frank Ch. Eigler <fche@elastic.org>
+ * main.cxx (main): Don't override $PATH etc.
+ * tapsets.cxx (base_query ctor, dwarf_builder::build,
+ itrace_builder, utrace_derived_probe): Use find_executable()
+ to resolve FOO path in process("FOO").
+ * util.cxx (find_executable): Duplicate execvp logic.
+
+2008-08-09 Frank Ch. Eigler <fche@elastic.org>
+
* util.cxx (find_executable): Reorganize, simplify, canonicalize.
* util.h, hash.cxx: Corresponding changes.
diff --git a/main.cxx b/main.cxx
index 8c99cf7e..a2ceb656 100644
--- a/main.cxx
+++ b/main.cxx
@@ -696,25 +696,11 @@ main (int argc, char * const argv [])
int rc = 0;
- // override PATH and LC_ALL
- const char *path = "/bin:/sbin:/usr/bin:/usr/sbin";
- rc = setenv("PATH", path, 1) || setenv("LC_ALL", "C", 1);
- if (rc)
- {
- const char* e = strerror (errno);
- cerr << "setenv (\"PATH=" << path << "\" + \"LC_ALL=C\"): "
- << e << endl;
- }
-
- // Get rid of a few standard environment variables (which might
- // cause us to do unintended things).
- rc = unsetenv("IFS") || unsetenv("CDPATH") || unsetenv("ENV")
- || unsetenv("BASH_ENV");
- if (rc)
- {
- const char* e = strerror (errno);
- cerr << "unsetenv failed: " << e << endl;
- }
+ // For PR1477, we used to override $PATH and $LC_ALL and other stuff
+ // here. We seem to use complete pathnames in
+ // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
+ // it interferes with util.cxx:find_executable(), used for $PATH
+ // resolution.
s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
@@ -993,6 +979,7 @@ main (int argc, char * const argv [])
if (rc || s.last_pass == 3 || pending_interrupts) goto cleanup;
// PASS 4: COMPILATION
+
times (& tms_before);
gettimeofday (&tv_before, NULL);
rc = compile_pass (s);
diff --git a/tapsets.cxx b/tapsets.cxx
index ab5713b0..66c9a7ac 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2357,7 +2357,11 @@ base_query::base_query(systemtap_session & sess,
if (has_module)
has_process = false;
else
- has_process = get_string_param(params, TOK_PROCESS, module_val);
+ {
+ has_process = get_string_param(params, TOK_PROCESS, module_val);
+ if (has_process)
+ module_val = find_executable (module_val);
+ }
assert (has_kernel || has_process || has_module);
}
@@ -5001,6 +5005,8 @@ dwarf_builder::build(systemtap_session & sess,
}
else if (get_param (parameters, TOK_PROCESS, module_name))
{
+ module_name = find_executable (module_name); // canonicalize it
+
// user-space target; we use one dwflpp instance per module name
// (= program or shared library)
if (user_dw.find(module_name) == user_dw.end())
@@ -5536,41 +5542,11 @@ struct itrace_builder: public derived_probe_builder
// If we have a path, we need to validate it.
if (has_path)
- {
- string::size_type start_pos, end_pos;
- string component;
-
- // Make sure it starts with '/'.
- if (path[0] != '/')
- throw semantic_error ("process path must start with a '/'",
- location->tok);
-
- start_pos = 1; // get past the initial '/'
- while ((end_pos = path.find('/', start_pos)) != string::npos)
- {
- component = path.substr(start_pos, end_pos - start_pos);
- // Make sure it isn't empty.
- if (component.size() == 0)
- throw semantic_error ("process path component cannot be empty",
- location->tok);
- // Make sure it isn't relative.
- else if (component == "." || component == "..")
- throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok);
-
- start_pos = end_pos + 1;
- }
- component = path.substr(start_pos);
- // Make sure it doesn't end with '/'.
- if (component.size() == 0)
- throw semantic_error ("process path cannot end with a '/'", location->tok);
- // Make sure it isn't relative.
- else if (component == "." || component == "..")
- throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok);
- }
+ path = find_executable (path);
finished_results.push_back(new itrace_derived_probe(sess, base, location,
has_path, path, pid,
- single_step
+ single_step
));
}
};
@@ -5809,13 +5785,54 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s,
probe* p, probe_point* l,
bool hp, string &pn, int64_t pd,
enum utrace_derived_probe_flags f):
- derived_probe(p, l), has_path(hp), path(pn), pid(pd), flags(f),
+ derived_probe (p, new probe_point (*l) /* .components soon rewritten */ ),
+ has_path(hp), path(pn), pid(pd), flags(f),
target_symbol_seen(false)
{
// Make a local-variable-expanded copy of the probe body
utrace_var_expanding_copy_visitor v (s, name, flags);
require <statement*> (&v, &(this->body), base->body);
target_symbol_seen = v.target_symbol_seen;
+
+ // Reset the sole element of the "locations" vector as a
+ // "reverse-engineered" form of the incoming (q.base_loc) probe
+ // point. This allows a user to see what program etc.
+ // number any particular match of the wildcards.
+
+ vector<probe_point::component*> comps;
+ if (hp)
+ comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(path)));
+ else
+ comps.push_back (new probe_point::component(TOK_PROCESS, new literal_number(pid)));
+ switch (flags)
+ {
+ case UDPF_THREAD_BEGIN:
+ comps.push_back (new probe_point::component(TOK_THREAD));
+ comps.push_back (new probe_point::component(TOK_BEGIN));
+ break;
+ case UDPF_THREAD_END:
+ comps.push_back (new probe_point::component(TOK_THREAD));
+ comps.push_back (new probe_point::component(TOK_END));
+ break;
+ case UDPF_SYSCALL:
+ comps.push_back (new probe_point::component(TOK_SYSCALL));
+ break;
+ case UDPF_SYSCALL_RETURN:
+ comps.push_back (new probe_point::component(TOK_SYSCALL));
+ comps.push_back (new probe_point::component(TOK_RETURN));
+ break;
+ case UDPF_BEGIN:
+ comps.push_back (new probe_point::component(TOK_BEGIN));
+ break;
+ case UDPF_END:
+ comps.push_back (new probe_point::component(TOK_END));
+ break;
+ default:
+ assert (0);
+ }
+
+ // Overwrite it.
+ this->sole_location()->components = comps;
}
@@ -5897,6 +5914,7 @@ struct utrace_builder: public derived_probe_builder
bool has_path = get_param (parameters, TOK_PROCESS, path);
bool has_pid = get_param (parameters, TOK_PROCESS, pid);
enum utrace_derived_probe_flags flags = UDPF_NONE;
+
assert (has_path || has_pid);
if (has_null_param (parameters, TOK_THREAD))
@@ -5921,39 +5939,7 @@ struct utrace_builder: public derived_probe_builder
// If we have a path, we need to validate it.
if (has_path)
{
- string::size_type start_pos, end_pos;
- string component;
-
- // XXX: these checks should be done in terms of filesystem
- // operations.
-
- // Make sure it starts with '/'.
- if (path[0] != '/')
- throw semantic_error ("process path must start with a '/'",
- location->tok);
-
- start_pos = 1; // get past the initial '/'
- while ((end_pos = path.find('/', start_pos)) != string::npos)
- {
- component = path.substr(start_pos, end_pos - start_pos);
- // Make sure it isn't empty.
- if (component.size() == 0)
- throw semantic_error ("process path component cannot be empty",
- location->tok);
- // Make sure it isn't relative.
- else if (component == "." || component == "..")
- throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok);
-
- start_pos = end_pos + 1;
- }
- component = path.substr(start_pos);
- // Make sure it doesn't end with '/'.
- if (component.size() == 0)
- throw semantic_error ("process path cannot end with a '/'", location->tok);
- // Make sure it isn't relative.
- else if (component == "." || component == "..")
- throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok);
-
+ path = find_executable (path);
sess.unwindsym_modules.insert (path);
}
diff --git a/util.cxx b/util.cxx
index 8be4ea5d..ab0a1a91 100644
--- a/util.cxx
+++ b/util.cxx
@@ -154,7 +154,10 @@ tokenize(const string& str, vector<string>& tokens,
}
-// Find an executable by name in $PATH.
+// Resolve an executable name to a canonical full path name, with the
+// same policy as execvp(). A program name not containing a slash
+// will be searched along the $PATH.
+
string find_executable(const string& name)
{
string retpath;
@@ -162,9 +165,13 @@ string find_executable(const string& name)
if (name.size() == 0)
return name;
- if (name[0] == '/') // already fully qualified
- retpath = name;
- else // need to search along $PATH
+ struct stat st;
+
+ if (name.find('/') != string::npos) // slash in the path already?
+ {
+ retpath = name;
+ }
+ else // Nope, search $PATH.
{
char *path = getenv("PATH");
if (path)
@@ -178,13 +185,11 @@ string find_executable(const string& name)
{
string fname = *i + "/" + name;
const char *f = fname.c_str();
- struct stat st1, st2;
// Look for a normal executable file.
if (access(f, X_OK) == 0
- && lstat(f, &st1) == 0
- && stat(f, &st2) == 0
- && S_ISREG(st2.st_mode))
+ && stat(f, &st) == 0
+ && S_ISREG(st.st_mode))
{
retpath = fname;
break;
@@ -193,6 +198,12 @@ string find_executable(const string& name)
}
}
+
+ // Could not find the program on the $PATH. We'll just fall back to
+ // the unqualified name, which our caller will probably fail with.
+ if (retpath == "")
+ retpath = name;
+
// Canonicalize the path name.
char *cf = canonicalize_file_name (retpath.c_str());
if (cf)