]> sourceware.org Git - systemtap.git/blame - util.h
Fix rawhide compile problems in aux_syscalls.stp.
[systemtap.git] / util.h
CommitLineData
42e38653
DB
1#ifndef UTIL_H
2#define UTIL_H
3
58a834b1 4#include "config.h"
fce2d171 5#include <cstdlib>
60d98537 6#include <cstring>
5e3b8687 7#include <cerrno>
1b78aef5
DS
8#include <string>
9#include <vector>
72dbc915
FCE
10#include <iostream>
11#include <sstream>
12#include <stdexcept>
3f99432c 13#include <cctype>
e4e3d6b7 14#include <set>
e1e8b44e 15#include <iomanip>
05fb3e0c 16#include <map>
004f2b9c 17#include <algorithm>
593f09eb 18#include <limits>
004f2b9c 19
a69b4b55 20extern "C" {
52c2652f 21#if ENABLE_NLS
58a834b1
LB
22#include <libintl.h>
23#include <locale.h>
52c2652f 24#endif
a69b4b55 25#include <signal.h>
f13fc0db 26#include <stdint.h>
aeb9cc10 27#include <spawn.h>
e1e8b44e 28#include <assert.h>
3f95ed01 29#include <poll.h>
f13fc0db 30}
1b78aef5 31
d6d4dc4b
JS
32// NB: GCC didn't add C++11 final/override until 4.7, but until then it also
33// only had __cplusplus=1 regardless of -std (GCC PR1773). So checking new
34// __cplusplus is probably good enough here; otherwise we should autoconf it.
35#if __cplusplus >= 201103L
36#define cxx_final final
37#define cxx_override override
38#else
39#define cxx_final
40#define cxx_override
41#endif
42
3892d516 43#include "privilege.h"
47d349b1 44#include "stringtable.h"
f2013cc9 45
58a834b1
LB
46#if ENABLE_NLS
47#define _(string) gettext(string)
48#define _N(string, string_plural, count) \
49 ngettext((string), (string_plural), (count))
50#else
51#define _(string) (string)
52#define _N(string, string_plural, count) \
53 ( (count) == 1 ? (string) : (string_plural) )
54#endif
55#define _F(format, ...) autosprintf(_(format), __VA_ARGS__)
56#define _NF(format, format_plural, count, ...) \
57 autosprintf(_N((format), (format_plural), (count)), __VA_ARGS__)
9e1a2390
JL
58#define _STRINGIFY_MORE(s) #s
59#define _STRINGIFY(s) _STRINGIFY_MORE(s)
a22da505 60#define ERR_SRC (std::string(__FILE__) + ":" + _STRINGIFY(__LINE__))
9e1a2390
JL
61#define SEMANTIC_ERROR(...) semantic_error(ERR_SRC, __VA_ARGS__)
62#define PARSE_ERROR(...) parse_error(ERR_SRC, __VA_ARGS__)
58a834b1 63
72dbc915 64const char *get_home_directory(void);
b12c8986 65size_t get_file_size(const std::string &path);
a5751672 66size_t get_file_size(int fd);
b12c8986 67bool file_exists (const std::string &path);
e16dc041
JS
68bool copy_file(const std::string& src, const std::string& dest,
69 bool verbose=false);
3b6f3bbb 70int create_dir(const char *dir, int mode = 0777);
98f552c2 71int remove_file_or_dir(const char *dir);
3892d516 72extern "C" gid_t get_gid (const char *group_name);
0da3e7a0 73bool in_group_id (gid_t target_gid);
85007c04 74std::string getmemusage ();
1b78aef5 75void tokenize(const std::string& str, std::vector<std::string>& tokens,
9c269440 76 const std::string& delimiters = " ");
49dbe419 77void tokenize_full(const std::string& str, std::vector<std::string>& tokens,
9c269440 78 const std::string& delimiters = " ");
91699a70 79void tokenize_cxx(const std::string& str, std::vector<std::string>& tokens);
004f2b9c 80std::vector<std::pair<const char*,int> > split_lines(const char *buf, size_t n);
0a567f6d 81std::string find_executable(const std::string& name);
63b4fd14 82std::string find_executable(const std::string& name,
05fb3e0c 83 const std::string& sysroot,
0a567f6d 84 const std::map<std::string,std::string>& sysenv,
63b4fd14 85 const std::string& env_path = "PATH");
dbe9d133
JL
86bool is_fully_resolved(const std::string& name,
87 const std::string& sysroot,
88 const std::map<std::string,std::string>& sysenv,
89 const std::string& env_path = "PATH");
8c711d30 90const std::string cmdstr_quoted(const std::string& cmd);
38bf68a8 91const std::string detox_path(const std::string& str);
5eea6ed1 92const std::string cmdstr_join(const std::vector<std::string>& cmds);
8fdd1f2e
DS
93const std::string join(const std::vector<std::string>& cmds,
94 const std::string& delim);
01cc94dc 95int stap_waitpid(int verbose, pid_t pid);
20f90026 96pid_t stap_spawn(int verbose, const std::vector<std::string>& args);
aeb9cc10 97pid_t stap_spawn(int verbose, const std::vector<std::string>& args,
e4e3d6b7 98 posix_spawn_file_actions_t* fa, const std::vector<std::string>& envVec = std::vector<std::string> ());
645383d5 99pid_t stap_spawn_piped(int verbose, const std::vector<std::string>& args,
e96f2257 100 int* child_in=NULL, int* child_out=NULL, int* child_err=NULL);
b13c6a37
JS
101int stap_system(int verbose, const std::string& description,
102 const std::vector<std::string>& args,
ff520ff4 103 bool null_out=false, bool null_err=false);
b13c6a37
JS
104inline int stap_system(int verbose, const std::vector<std::string>& args,
105 bool null_out=false, bool null_err=false)
106{ return stap_system(verbose, args.front(), args, null_out, null_err); }
20f90026 107int stap_system_read(int verbose, const std::vector<std::string>& args, std::ostream& out);
9a9be966 108std::pair<bool,int> stap_fork_read(int verbose, std::ostream& out);
4cc40e82 109int kill_stap_spawn(int sig);
c0d1b5a0 110void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re);
8aabf152 111int regexp_match (const std::string& value, const std::string& re, std::vector<std::string>& matches);
37001baa 112bool contains_glob_chars (const std::string &str);
5750ecc6
FCE
113std::string escape_glob_chars (const std::string& str);
114std::string unescape_glob_chars (const std::string& str);
e207d98f
MW
115bool identifier_string_needs_escape (const std::string& str);
116std::string escaped_indentifier_string (const std::string& str);
aeb9cc10 117std::string kernel_release_from_build_tree (const std::string &kernel_build_tree, int verbose = 0);
daa75206 118std::string normalize_machine(const std::string& machine);
081b45d1 119int elf_class_from_normalized_machine(const std::string& machine);
2695da79 120std::string autosprintf(const char* format, ...) __attribute__ ((format (printf, 1, 2)));
e4e3d6b7 121const std::set<std::string>& localization_variables();
28946fe7 122std::string get_self_path();
a03a3744 123bool is_valid_pid (pid_t pid, std::string& err_msg);
72dbc915
FCE
124
125// stringification generics
126
127
aca66a36
JS
128template <typename IN>
129inline std::string lex_cast(IN const & in)
72dbc915 130{
aca66a36
JS
131 std::ostringstream ss;
132 if (!(ss << in))
58a834b1 133 throw std::runtime_error(_("bad lexical cast"));
aca66a36 134 return ss.str();
72dbc915
FCE
135}
136
137
aca66a36
JS
138template <typename OUT>
139inline OUT lex_cast(std::string const & in)
72dbc915 140{
aca66a36 141 std::istringstream ss(in);
72dbc915 142 OUT out;
aca66a36 143 if (!(ss >> out && ss.eof()))
58a834b1 144 throw std::runtime_error(_("bad lexical cast"));
72dbc915
FCE
145 return out;
146}
147
148
f13fc0db
JS
149// We want [u]int8_t to be treated numerically, not just extracting a char.
150template <>
151inline int8_t lex_cast(std::string const & in)
152{
153 int16_t out = lex_cast<int16_t>(in);
154 if (out < -128 || out > 127)
58a834b1 155 throw std::runtime_error(_("bad lexical cast"));
f13fc0db
JS
156 return out;
157}
158template <>
159inline uint8_t lex_cast(std::string const & in)
160{
161 uint16_t out = lex_cast<uint16_t>(in);
162 if (out > 0xff && out < 0xff80) // don't error if it looks sign-extended
58a834b1 163 throw std::runtime_error(_("bad lexical cast"));
f13fc0db
JS
164 return out;
165}
166
167
aca66a36
JS
168template <typename IN>
169inline std::string
72dbc915
FCE
170lex_cast_hex(IN const & in)
171{
aca66a36 172 std::ostringstream ss;
49e1b0a1 173 if (!(ss << std::showbase << std::hex << in << std::dec))
58a834b1 174 throw std::runtime_error(_("bad lexical cast"));
aca66a36 175 return ss.str();
72dbc915
FCE
176}
177
e1e8b44e
CM
178//Convert binary data to hex data.
179template <typename IN>
180inline std::string
181hex_dump(IN const & in, size_t len)
182{
183 std::ostringstream ss;
184 unsigned i;
185 if (!(ss << std::hex << std::setfill('0')))
186 throw std::runtime_error(_("bad lexical cast"));
187
188 for(i = 0; i < len; i++)
189 {
190 int temp = in[i];
191 ss << std::setw(2) << temp;
192 }
193 std::string hex = ss.str();
194 assert(hex.length() == 2 * len);
195 return hex;
196}
72dbc915
FCE
197
198// Return as quoted string, so that when compiled as a C literal, it
199// would print to the user out nicely.
dff50e09 200template <typename IN>
72dbc915
FCE
201inline std::string
202lex_cast_qstring(IN const & in)
203{
204 std::stringstream ss;
72dbc915 205 if (!(ss << in))
58a834b1 206 throw std::runtime_error(_("bad lexical cast"));
aca66a36
JS
207 return lex_cast_qstring(ss.str());
208}
209
210
211template <>
212inline std::string
213lex_cast_qstring(std::string const & in)
214{
215 std::string out;
216 out += '"';
217 for (const char *p = in.c_str(); *p; ++p)
72dbc915 218 {
aca66a36 219 unsigned char c = *p;
3f99432c
FCE
220 if (! isprint(c))
221 {
aca66a36 222 out += '\\';
3f99432c 223 // quick & dirty octal converter
aca66a36
JS
224 out += "01234567" [(c >> 6) & 0x07];
225 out += "01234567" [(c >> 3) & 0x07];
226 out += "01234567" [(c >> 0) & 0x07];
dff50e09 227 }
3f99432c
FCE
228 else if (c == '"' || c == '\\')
229 {
aca66a36
JS
230 out += '\\';
231 out += c;
3f99432c
FCE
232 }
233 else
aca66a36 234 out += c;
72dbc915 235 }
aca66a36
JS
236 out += '"';
237 return out;
72dbc915 238}
73267b89 239
c9efa5c9
JS
240
241// Delete all values from a map-like container and clear it
242// (The template is permissive -- be good!)
243template <typename T>
244void delete_map(T& t)
245{
246 for (typename T::iterator i = t.begin(); i != t.end(); ++i)
247 delete i->second;
248 t.clear();
249}
250
251
4cb10751
CM
252// Automatically save a variable, and restore it at the
253// end of the function.
254template <class V>
255class save_and_restore
256{
257 V* ptr;
258 V previous_value;
259
260 public:
261 // Optionally pass a second argument to the constructor to initialize the
262 // variable to some value, after saving its old value.
263 save_and_restore(V* ptr_in, V value_in): ptr(ptr_in), previous_value(*ptr_in) { *ptr_in = value_in; }
264 save_and_restore(V*ptr_in): ptr(ptr_in), previous_value(*ptr_in){}
265
266 // Retrieve the old value and restore it in the destructor
267 ~save_and_restore() { *ptr = previous_value; }
268};
269
004f2b9c
JL
270template <typename T>
271inline bool vector_has(std::vector<T>& v, T item)
272{
273 return std::find(v.begin(), v.end(), item) != v.end();
274}
4cb10751 275
60d98537
JS
276// Returns whether a string starts with the given prefix
277inline bool
278startswith(const std::string & s, const char * prefix)
279{
280 return (s.compare(0, std::strlen(prefix), prefix) == 0);
281}
282
5bca76a8
JS
283inline bool
284startswith(const std::string & s, const std::string & prefix)
285{
286 return (s.compare(0, prefix.length(), prefix) == 0);
287}
288
60d98537
JS
289// Returns whether a string ends with the given suffix
290inline bool
291endswith(const std::string & s, const char * suffix)
292{
293 size_t s_len = s.size(), suffix_len = std::strlen(suffix);
294 if (suffix_len > s_len)
295 return false;
296 return (s.compare(s_len - suffix_len, suffix_len, suffix) == 0);
297}
298
299
a69b4b55
JS
300// Mask our usual signals for the life of this object.
301struct stap_sigmasker {
302 sigset_t old;
303 stap_sigmasker()
304 {
305 sigset_t mask;
306 sigemptyset (&mask);
307 sigaddset (&mask, SIGHUP);
308 sigaddset (&mask, SIGPIPE);
309 sigaddset (&mask, SIGINT);
310 sigaddset (&mask, SIGTERM);
311 sigprocmask (SIG_BLOCK, &mask, &old);
312 }
6d27dcff
JS
313 stap_sigmasker(const sigset_t *mask)
314 {
315 sigprocmask (SIG_BLOCK, mask, &old);
316 }
a69b4b55
JS
317 ~stap_sigmasker()
318 {
319 sigprocmask (SIG_SETMASK, &old, NULL);
320 }
321};
322
fce2d171
JS
323// Convert a possibly-relative path to a full path
324inline std::string
325resolve_path(const std::string& path)
326{
327 std::string result(path);
328 char* resolved_path = realpath(path.c_str(), NULL);
329 if (resolved_path)
330 {
331 result = resolved_path;
332 std::free(resolved_path);
333 }
334 return result;
335}
336
cde0f3ce
JL
337// Used in levenshtein
338template<typename T>
339class Array2D
340{
341 private:
342 T * data;
343 public:
344 const unsigned width;
345 const unsigned height;
346 T& operator() (unsigned x, unsigned y) { return data[y*width + x]; }
347 Array2D(const unsigned w, const unsigned h) : width(w), height(h) { data = new T[w*h]; }
348 ~Array2D() { delete [] data; }
349};
350
351// String sorter using the Levenshtein algorithm
352unsigned levenshtein(const std::string& a, const std::string& b);
fce2d171 353
593f09eb
JL
354// Returns comma-separated list of set elements closest to the target string.
355// Print a maximum amount of 'max' elements, with a maximum levenshtein score
356// of 'threshold'.
357std::string levenshtein_suggest(const std::string& target,
358 const std::set<std::string>& elems,
359 unsigned max = std::numeric_limits<unsigned>::max(),
360 unsigned threshold = std::numeric_limits<unsigned>::max());
361
a3e980f9 362std::string levenshtein_suggest(const std::string& target,
47d349b1 363 const std::set<interned_string>& elems,
a3e980f9
FCE
364 unsigned max = std::numeric_limits<unsigned>::max(),
365 unsigned threshold = std::numeric_limits<unsigned>::max());
366
3f95ed01
JS
367#ifndef HAVE_PPOLL
368// This is a poor-man's ppoll; see the implementation for more details...
369int ppoll(struct pollfd *fds, nfds_t nfds,
370 const struct timespec *timeout_ts,
371 const sigset_t *sigmask);
372#endif
373
374
42e38653 375#endif // UTIL_H
a69b4b55 376
73267b89 377/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.205654 seconds and 5 git commands to generate.