32 // Sanity check C++11 support. We're only requiring GCC 4.4's level of
33 // functionality, so trust either __cplusplus or the GNUC macros.
34 #if !(__cplusplus >= 201103L || \
35 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)))
36 #error "C++11 support is required!"
39 // NB: GCC didn't add C++11 final/override until 4.7, but until then it also
40 // only had __cplusplus=1 regardless of -std (GCC PR1773). So checking new
41 // __cplusplus is probably good enough here; otherwise we should autoconf it.
42 #if __cplusplus >= 201103L
43 #define cxx_final final
44 #define cxx_override override
50 #include "privilege.h"
51 #include "stringtable.h"
54 #define _(string) gettext(string)
55 #define _N(string, string_plural, count) \
56 ngettext((string), (string_plural), (count))
58 #define _(string) (string)
59 #define _N(string, string_plural, count) \
60 ( (count) == 1 ? (string) : (string_plural) )
62 #define _F(format, ...) autosprintf(_(format), __VA_ARGS__)
63 #define _NF(format, format_plural, count, ...) \
64 autosprintf(_N((format), (format_plural), (count)), __VA_ARGS__)
65 #define _STRINGIFY_MORE(s) #s
66 #define _STRINGIFY(s) _STRINGIFY_MORE(s)
67 #define ERR_SRC (std::string(__FILE__) + ":" + _STRINGIFY(__LINE__))
68 #define SEMANTIC_ERROR(...) semantic_error(ERR_SRC, __VA_ARGS__)
69 #define PARSE_ERROR(...) parse_error(ERR_SRC, __VA_ARGS__)
71 const char *get_home_directory(void);
72 size_t get_file_size(const std::string
&path
);
73 size_t get_file_size(int fd
);
74 bool file_exists (const std::string
&path
);
75 bool dir_exists(const std::string
&path
);
76 bool copy_file(const std::string
& src
, const std::string
& dest
,
78 int create_dir(const char *dir
, int mode
= 0777);
79 int remove_file_or_dir(const char *dir
);
80 extern "C" gid_t
get_gid (const char *group_name
);
81 int appendenv (const char *env_name
, const std::string source
);
82 bool in_group_id (gid_t target_gid
);
83 std::string
getmemusage ();
84 void tokenize(const std::string
& str
, std::vector
<std::string
>& tokens
,
85 const std::string
& delimiters
= " ");
86 void tokenize_full(const std::string
& str
, std::vector
<std::string
>& tokens
,
87 const std::string
& delimiters
= " ");
88 void tokenize_cxx(const std::string
& str
, std::vector
<std::string
>& tokens
);
89 std::vector
<std::pair
<const char*,int> > split_lines(const char *buf
, size_t n
);
90 std::string
find_executable(const std::string
& name
);
91 std::string
find_executable(const std::string
& name
,
92 const std::string
& sysroot
,
93 const std::map
<std::string
,std::string
>& sysenv
,
94 const std::string
& env_path
= "PATH");
95 bool is_fully_resolved(const std::string
& name
,
96 const std::string
& sysroot
,
97 const std::map
<std::string
,std::string
>& sysenv
,
98 const std::string
& env_path
= "PATH");
99 const std::string
cmdstr_quoted(const std::string
& cmd
);
100 const std::string
detox_path(const std::string
& str
);
101 const std::string
cmdstr_join(const std::vector
<std::string
>& cmds
);
102 const std::string
join(const std::vector
<std::string
>& cmds
,
103 const std::string
& delim
);
104 int stap_waitpid(int verbose
, pid_t pid
);
105 pid_t
stap_spawn(int verbose
, const std::vector
<std::string
>& args
);
106 pid_t
stap_spawn(int verbose
, const std::vector
<std::string
>& args
,
107 posix_spawn_file_actions_t
* fa
, const std::vector
<std::string
>& envVec
= std::vector
<std::string
> ());
108 pid_t
stap_spawn_piped(int verbose
, const std::vector
<std::string
>& args
,
109 int* child_in
=NULL
, int* child_out
=NULL
, int* child_err
=NULL
);
110 int stap_system(int verbose
, const std::string
& description
,
111 const std::vector
<std::string
>& args
,
112 bool null_out
=false, bool null_err
=false);
113 inline int stap_system(int verbose
, const std::vector
<std::string
>& args
,
114 bool null_out
=false, bool null_err
=false)
115 { return stap_system(verbose
, args
.front(), args
, null_out
, null_err
); }
116 int stap_system_read(int verbose
, const std::vector
<std::string
>& args
, std::ostream
& out
);
117 std::pair
<bool,int> stap_fork_read(int verbose
, std::ostream
& out
);
118 int kill_stap_spawn(int sig
);
119 void assert_regexp_match (const std::string
& name
, const std::string
& value
, const std::string
& re
);
120 int regexp_match (const std::string
& value
, const std::string
& re
, std::vector
<std::string
>& matches
);
121 bool contains_glob_chars (const std::string
&str
);
122 std::string
escape_glob_chars (const std::string
& str
);
123 std::string
unescape_glob_chars (const std::string
& str
);
124 std::string
csh_to_ksh (const std::string
& csh
);
125 bool identifier_string_needs_escape (const std::string
& str
);
126 std::string
escaped_identifier_string (const std::string
& str
);
127 std::string
escaped_character (unsigned c
);
128 std::string
escaped_literal_string (const std::string
& str
);
129 std::string
kernel_release_from_build_tree (const std::string
&kernel_build_tree
, int verbose
= 0);
130 std::string
normalize_machine(const std::string
& machine
);
131 int elf_class_from_normalized_machine(const std::string
& machine
);
132 std::string
autosprintf(const char* format
, ...) __attribute__ ((format (printf
, 1, 2)));
133 const std::set
<std::string
>& localization_variables();
134 std::string
get_self_path();
135 bool is_valid_pid (pid_t pid
, std::string
& err_msg
);
137 // stringification generics
140 template <typename IN
>
141 inline std::string
lex_cast(IN
const & in
)
143 std::ostringstream ss
;
145 throw std::runtime_error(_("bad lexical cast"));
149 #if __cplusplus < 201103L
150 // Older C++0x only had the "long long" implementations, so we cast up.
151 #define INT_TO_STRING(IN) \
152 LEX_CAST_TO_STRING(signed IN, long long) \
153 LEX_CAST_TO_STRING(unsigned IN, unsigned long long)
155 // Otherwise, keep the values native.
156 #define INT_TO_STRING(IN) \
157 LEX_CAST_TO_STRING(signed IN, signed IN) \
158 LEX_CAST_TO_STRING(unsigned IN, unsigned IN)
161 #define LEX_CAST_TO_STRING(IN, CAST) \
163 inline std::string lex_cast(IN const & in) \
165 return std::to_string(static_cast<CAST>(in)); \
172 INT_TO_STRING(long long)
175 #undef LEX_CAST_TO_STRING
178 template <typename OUT
>
179 inline OUT
lex_cast(std::string
const & in
)
181 std::istringstream
ss(in
);
183 if (!(ss
>> out
&& ss
.eof()))
184 throw std::runtime_error(_("bad lexical cast"));
189 // We want [u]int8_t to be treated numerically, not just extracting a char.
191 inline int8_t lex_cast(std::string
const & in
)
193 int16_t out
= lex_cast
<int16_t>(in
);
194 if (out
< -128 || out
> 127)
195 throw std::runtime_error(_("bad lexical cast"));
199 inline uint8_t lex_cast(std::string
const & in
)
201 uint16_t out
= lex_cast
<uint16_t>(in
);
202 if (out
> 0xff && out
< 0xff80) // don't error if it looks sign-extended
203 throw std::runtime_error(_("bad lexical cast"));
208 template <typename IN
>
210 lex_cast_hex(IN
const & in
)
212 std::ostringstream ss
;
213 if (!(ss
<< std::showbase
<< std::hex
<< in
<< std::dec
))
214 throw std::runtime_error(_("bad lexical cast"));
218 //Convert binary data to hex data.
219 template <typename IN
>
221 hex_dump(IN
const & in
, size_t len
)
223 std::ostringstream ss
;
225 if (!(ss
<< std::hex
<< std::setfill('0')))
226 throw std::runtime_error(_("bad lexical cast"));
228 for(i
= 0; i
< len
; i
++)
231 ss
<< std::setw(2) << temp
;
233 std::string hex
= ss
.str();
234 assert(hex
.length() == 2 * len
);
238 // Return as quoted string, so that when compiled as a C literal, it
239 // would print to the user out nicely.
240 template <typename IN
>
242 lex_cast_qstring(IN
const & in
)
244 std::stringstream ss
;
246 throw std::runtime_error(_("bad lexical cast"));
247 return lex_cast_qstring(ss
.str());
253 lex_cast_qstring(std::string
const & in
)
257 for (const char *p
= in
.c_str(); *p
; ++p
)
259 unsigned char c
= *p
;
263 // quick & dirty octal converter
264 out
+= "01234567" [(c
>> 6) & 0x07];
265 out
+= "01234567" [(c
>> 3) & 0x07];
266 out
+= "01234567" [(c
>> 0) & 0x07];
268 else if (c
== '"' || c
== '\\')
281 // Delete all values from a map-like container and clear it
282 // (The template is permissive -- be good!)
283 template <typename T
>
284 void delete_map(T
& t
)
286 for (typename
T::iterator i
= t
.begin(); i
!= t
.end(); ++i
)
292 // Automatically save a variable, and restore it at the
293 // end of the function.
295 class save_and_restore
301 // Optionally pass a second argument to the constructor to initialize the
302 // variable to some value, after saving its old value.
303 save_and_restore(V
* ptr_in
, V value_in
): ptr(ptr_in
), previous_value(*ptr_in
) { *ptr_in
= value_in
; }
304 save_and_restore(V
*ptr_in
): ptr(ptr_in
), previous_value(*ptr_in
){}
306 // Retrieve the old value and restore it in the destructor
307 ~save_and_restore() { *ptr
= previous_value
; }
310 template <typename T
>
311 inline bool vector_has(std::vector
<T
>& v
, T item
)
313 return std::find(v
.begin(), v
.end(), item
) != v
.end();
316 // Returns whether a string starts with the given prefix
318 startswith(const std::string
& s
, const char * prefix
)
320 return (s
.compare(0, std::strlen(prefix
), prefix
) == 0);
324 startswith(const std::string
& s
, const std::string
& prefix
)
326 return (s
.compare(0, prefix
.length(), prefix
) == 0);
329 // Returns whether a string ends with the given suffix
331 endswith(const std::string
& s
, const char * suffix
)
333 size_t s_len
= s
.size(), suffix_len
= std::strlen(suffix
);
334 if (suffix_len
> s_len
)
336 return (s
.compare(s_len
- suffix_len
, suffix_len
, suffix
) == 0);
340 // Mask our usual signals for the life of this object.
341 struct stap_sigmasker
{
347 sigaddset (&mask
, SIGHUP
);
348 sigaddset (&mask
, SIGPIPE
);
349 sigaddset (&mask
, SIGINT
);
350 sigaddset (&mask
, SIGTERM
);
351 sigprocmask (SIG_BLOCK
, &mask
, &old
);
353 stap_sigmasker(const sigset_t
*mask
)
355 sigprocmask (SIG_BLOCK
, mask
, &old
);
359 sigprocmask (SIG_SETMASK
, &old
, NULL
);
363 // Convert a possibly-relative path to a full path
365 resolve_path(const std::string
& path
)
367 std::string
result(path
);
368 char* resolved_path
= realpath(path
.c_str(), NULL
);
371 result
= resolved_path
;
372 std::free(resolved_path
);
377 // Used in levenshtein
384 const unsigned width
;
385 const unsigned height
;
386 T
& operator() (unsigned x
, unsigned y
) { return data
[y
*width
+ x
]; }
387 Array2D(const unsigned w
, const unsigned h
) : width(w
), height(h
) { data
= new T
[w
*h
]; }
388 ~Array2D() { delete [] data
; }
391 // String sorter using the Levenshtein algorithm
392 unsigned levenshtein(const std::string
& a
, const std::string
& b
);
394 // Returns comma-separated list of set elements closest to the target string.
395 // Print a maximum amount of 'max' elements, with a maximum levenshtein score
397 std::string
levenshtein_suggest(const std::string
& target
,
398 const std::set
<std::string
>& elems
,
399 unsigned max
= std::numeric_limits
<unsigned>::max(),
400 unsigned threshold
= std::numeric_limits
<unsigned>::max());
402 std::string
levenshtein_suggest(const std::string
& target
,
403 const std::set
<interned_string
>& elems
,
404 unsigned max
= std::numeric_limits
<unsigned>::max(),
405 unsigned threshold
= std::numeric_limits
<unsigned>::max());
408 // This is a poor-man's ppoll; see the implementation for more details...
409 int ppoll(struct pollfd
*fds
, nfds_t nfds
,
410 const struct timespec
*timeout_ts
,
411 const sigset_t
*sigmask
);
415 int read_from_file (const std::string
&fname
, int &data
);
417 int write_to_file (const std::string
&fname
, const T
&data
);
418 int flush_to_stream (const std::string
&fname
, std::ostream
&o
);
420 void ltrim(std::string
&s
);
421 void rtrim(std::string
&s
);
422 void trim(std::string
&s
);
424 bool get_distro_info(std::vector
<std::string
> &info
);
427 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */