This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: fix 12099 -- quick review?
Thanks Frank for the review, here is the C++ iostreams version.
Rayson
diff --git a/tapsets.cxx b/tapsets.cxx
index a8970bc..86b1552 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -30,6 +30,7 @@
#include <cstdlib>
#include <algorithm>
#include <deque>
+#include <fstream>
#include <iostream>
#include <map>
#include <set>
@@ -56,6 +57,7 @@ extern "C" {
#include <math.h>
#include <regex.h>
#include <unistd.h>
+#include <limits.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
@@ -5823,6 +5825,78 @@ dwarf_builder::build(systemtap_session & sess,
}
user_path = find_executable (module_name); // canonicalize it
+
+
+ // if the executable starts with "#!", we look for the
interpreter of the script
+ {
+ ifstream script_file (user_path.c_str());
+
+ if (script_file.good())
+ {
+ char buffer[PATH_MAX + 1 + 2]; // max path len + \n + #!
+
+ script_file.getline(buffer, sizeof(buffer));
+
+ if (buffer[0] != '\0')
+ {
+ size_t plen = strlen (buffer);
+
+ if (plen > sizeof ("#!") && memcmp (buffer, "#!", sizeof
("#!")-1) == 0)
+ {
+ // remove white spaces at the end of the string
+ plen--;
+
+ while (buffer[plen] == '\n' || buffer[plen] == ' ' ||
buffer[plen] == '\t')
+ {
+ buffer[plen] = '\0';
+ plen--;
+ }
+
+ // move pass #! and white spaces at the beginning of the string
+ char *path = buffer+2;
+
+ while (*path == ' ' || *path == '\t')
+ path++;
+
+ user_path = find_executable (string (path));
+
+ struct stat st;
+
+ if (access (user_path.c_str(), X_OK) == 0
+ && stat (user_path.c_str(), &st) == 0
+ && S_ISREG (st.st_mode)) // see find_executable()
+ {
+
+ if (sess.verbose > 1)
+ clog << "Expanded process(\"" << module_name << "\") to "
+ << "process(\"" << user_path << "\")" << endl;
+
+ assert (location->components.size() > 0);
+ assert (location->components[0]->functor == TOK_PROCESS);
+ assert (location->components[0]->arg);
+ literal_string* lit =
dynamic_cast<literal_string*>(location->components[0]->arg);
+ assert (lit);
+
+ // synthesize a new probe_point, with the expanded string
+ probe_point *pp = new probe_point (*location);
+ probe_point::component* ppc = new
probe_point::component (TOK_PROCESS,
+
new literal_string (user_path.c_str()));
+ ppc->tok = location->components[0]->tok; //
overwrite [0] slot, pattern matched above
+ pp->components[0] = ppc;
+
+ probe* new_probe = new probe (*base, pp);
+
+ derive_probes (sess, new_probe, finished_results);
+
+ script_file.close();
+ return;
+ }
+ }
+ }
+ script_file.close();
+ }
+ }
+
if (get_param (parameters, TOK_LIBRARY, library_name))
{
module_name = find_executable (library_name, "LD_LIBRARY_PATH");
On Thu, Nov 25, 2010 at 5:43 PM, Frank Ch. Eigler <fche@redhat.com> wrote:
> Rayson Ho <raysonlogin@gmail.com> writes:
>
>> I am going to check the code in if no one has complains about the fix.
>
>> + ? ? ? ? FILE *fp = fopen (user_path.c_str(), "r");
>> + ? ? ? ? if (fp != NULL)
>> + ? ? ? ? {
>> + ? ? ? ? ? char buffer[PATH_MAX + 1 + 2]; // max path len + \n + #!
>> + ? ? ? ? ? if (fgets (buffer, PATH_MAX + 1 + 2, fp))
>> + ? ? ? ? ? ? size_t plen = strlen (buffer);
>> + ? ? ? ? ? ? if (plen > sizeof ("#!") && memcmp (buffer, "#!", sizeof
>> ("#!")-1) == 0)
>> + ? ? ? ? ? ? {
>> [...]
>
> I bet it would be simpler if the code used c++ iostreams rather than
> C stdio in order to parse first line of the shell script.
>
> - FChE
>