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