]> sourceware.org Git - systemtap.git/blame - main.cxx
Fix: Enhance -p option checking so as to just accept valid number
[systemtap.git] / main.cxx
CommitLineData
f4b28491 1// systemtap translator/driver
e7a0bd52 2// Copyright (C) 2005-2009 Red Hat Inc.
f12b2552 3// Copyright (C) 2005 IBM Corp.
77a5c1f9 4// Copyright (C) 2006 Intel Corporation.
69c68955
FCE
5//
6// This file is part of systemtap, and is free software. You can
7// redistribute it and/or modify it under the terms of the GNU General
8// Public License (GPL); either version 2, or (at your option) any
9// later version.
2b066ec1
FCE
10
11#include "config.h"
12#include "staptree.h"
13#include "parse.h"
14#include "elaborate.h"
15#include "translate.h"
f4b28491 16#include "buildrun.h"
dc38c0ae 17#include "session.h"
1b78aef5
DS
18#include "hash.h"
19#include "cache.h"
20#include "util.h"
c3a3c0c9 21#include "coveragedb.h"
c0f9d4b0 22#include "git_version.h"
2b066ec1
FCE
23
24#include <iostream>
25#include <fstream>
26#include <sstream>
f4b28491 27#include <cerrno>
24cb178f 28#include <cstdlib>
e00f99a7 29#include <limits.h>
2b066ec1
FCE
30
31extern "C" {
32#include <glob.h>
33#include <unistd.h>
49abf162 34#include <signal.h>
f4b28491 35#include <sys/utsname.h>
5ee1c56b 36#include <sys/times.h>
1d738eed 37#include <sys/time.h>
f59e98c4 38#include <sys/stat.h>
f4b28491 39#include <time.h>
f8949662 40#include <elfutils/libdwfl.h>
5f0a03a6 41#include <getopt.h>
2b066ec1
FCE
42}
43
44using namespace std;
45
46
f4b28491 47void
c0de7a8d 48version ()
2b066ec1 49{
d54d4661 50 clog
d04cf5ff 51 << "SystemTap translator/driver "
c4a94c1a 52 << "(version " << VERSION << "/" << dwfl_version (NULL)
2881ab63 53 << " " << GIT_MESSAGE << ")" << endl
e7a0bd52 54 << "Copyright (C) 2005-2009 Red Hat, Inc. and others" << endl
f8949662 55 << "This is free software; see the source for copying conditions." << endl;
c0de7a8d
FCE
56}
57
58void
277c1957 59usage (systemtap_session& s, int exitcode)
c0de7a8d
FCE
60{
61 version ();
62 clog
f4b28491 63 << endl
b2d5d95c 64 << "Usage: stap [options] FILE Run script in file."
f4b28491 65 << endl
b2d5d95c 66 << " or: stap [options] - Run script on stdin."
f4b28491 67 << endl
d54d4661 68 << " or: stap [options] -e SCRIPT Run given script."
f4b28491 69 << endl
16442b90
FCE
70 << " or: stap [options] -l PROBE List matching probes."
71 << endl
d4e35ac8
WH
72 << " or: stap [options] -L PROBE List matching probes and local variables."
73 << endl
f4b28491 74 << endl
c0de7a8d 75 << "Options:" << endl
16442b90 76 << " -- end of translator options, script options follow" << endl
c0de7a8d
FCE
77 << " -h show help" << endl
78 << " -V show version" << endl
e0b4e89d
FCE
79 << " -p NUM stop after pass NUM 1-5, instead of " << s.last_pass << endl
80 << " (parse, elaborate, translate, compile, run)" << endl
81 << " -v add verbosity to all passes" << endl
82 << " --vp {N}+ add per-pass verbosity [";
83 for (unsigned i=0; i<5; i++)
84 clog << (s.perpass_verbose[i] <= 9 ? s.perpass_verbose[i] : 9);
85 clog
86 << "]" << endl
d5d7c2cc 87 << " -k keep temporary directory" << endl
cbfbbf69 88 << " -u unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl
a9e8f7e0 89 << " -w suppress warnings" << (s.suppress_warnings ? " [set]" : "") << endl
377b8831 90 << " -g guru mode" << (s.guru_mode ? " [set]" : "") << endl
dff50e09 91 << " -P prologue-searching for function probes"
44f75386 92 << (s.prologue_searching ? " [set]" : "") << endl
6dfd08d7 93 << " -b bulk (percpu file) mode" << (s.bulk_mode ? " [set]" : "") << endl
e0b4e89d 94 << " -s NUM buffer size in megabytes, instead of " << s.buffer_size << endl
f4b28491
FCE
95 << " -I DIR look in DIR for additional .stp script files";
96 if (s.include_path.size() == 0)
0d49d7bc 97 clog << endl;
f4b28491 98 else
24cb178f 99 clog << ", in addition to" << endl;
f4b28491 100 for (unsigned i=0; i<s.include_path.size(); i++)
0d49d7bc
FCE
101 clog << " " << s.include_path[i] << endl;
102 clog
ed10c639 103 << " -D NM=VAL emit macro definition into generated C code" << endl
24cb178f 104 << " -R DIR look in DIR for runtime, instead of" << endl
b5e66ada
FCE
105 << " " << s.runtime_path << endl
106 << " -r DIR cross-compile to kernel with given build tree; or else" << endl
107 << " -r RELEASE cross-compile to kernel /lib/modules/RELEASE/build, instead of" << endl
108 << " " << s.kernel_build_tree << endl
109 << " -m MODULE set probe module name, instead of " << endl
110 << " " << s.module_name << endl
04ae1b09 111 << " -o FILE send script output to file, instead of stdout. This supports" << endl
54f1da8f 112 << " strftime(3) formats for FILE" << endl
b5e66ada 113 << " -c CMD start the probes, run CMD, and exit when it finishes" << endl
4c5ff1bb 114 << " -x PID sets target() to PID" << endl
701c41be
MH
115 << " -F run as on-file flight recorder with -o." << endl
116 << " run as on-memory flight recorder without -o." << endl
117 << " -S size[,n] set maximum of the size and the number of files." << endl
a8368458
FCE
118 << " -d OBJECT add unwind/symbol data for OBJECT file";
119 if (s.unwindsym_modules.size() == 0)
120 clog << endl;
121 else
122 clog << ", in addition to" << endl;
1a0dbc5a
FCE
123 {
124 vector<string> syms (s.unwindsym_modules.begin(), s.unwindsym_modules.end());
125 for (unsigned i=0; i<syms.size(); i++)
126 clog << " " << syms[i] << endl;
127 }
a8368458 128 clog
cbd6fc7b 129 << " -t collect probe timing information" << endl
1c0b94ef 130#ifdef HAVE_LIBSQLITE3
5f0a03a6 131 << " -q generate information on tapset coverage" << endl
1c0b94ef 132#endif /* HAVE_LIBSQLITE3 */
05ec91b4 133#if 0 /* PR6864: disable temporarily; should merge with -d somehow */
5f0a03a6
JK
134 << " --kelf make do with symbol table from vmlinux" << endl
135 << " --kmap[=FILE]" << endl
136 << " make do with symbol table from nm listing" << endl
05ec91b4
FCE
137#endif
138 // Formerly present --ignore-{vmlinux,dwarf} options are for testsuite use
139 // only, and don't belong in the eyesight of a plain user.
3bd0d4df
RA
140 << " --skip-badvars" << endl
141 << " overlook context of bad $ variables" << endl
c3a3c0c9 142 << endl
d5d7c2cc 143 ;
2b066ec1 144
277c1957 145 exit (exitcode);
2b066ec1
FCE
146}
147
148
1b78aef5
DS
149static void
150printscript(systemtap_session& s, ostream& o)
151{
16442b90 152 if (s.listing_mode)
83d7fcdc 153 {
16442b90
FCE
154 // We go through some heroic measures to produce clean output.
155 set<string> seen;
83d7fcdc 156
16442b90 157 for (unsigned i=0; i<s.probes.size(); i++)
9ba8c134 158 {
f76427a2
FCE
159 if (pending_interrupts) return;
160
16442b90
FCE
161 derived_probe* p = s.probes[i];
162 // NB: p->basest() is not so interesting;
163 // p->almost_basest() doesn't quite work, so ...
164 vector<probe*> chain;
165 p->collect_derivation_chain (chain);
166 probe* second = (chain.size()>1) ? chain[chain.size()-2] : chain[0];
167
168 #if 0
169 cerr << "\tchain[" << chain.size() << "]:" << endl;
170 for (unsigned i=0; i<chain.size(); i++)
171 { cerr << "\t"; chain[i]->printsig(cerr); cerr << endl; }
172 #endif
173
174 stringstream tmps;
7fb2f650
FCE
175 const probe_alias *a = second->get_alias();
176 if (a)
177 {
178 assert (a->alias_names.size() >= 1);
179 a->alias_names[0]->print(tmps); // XXX: [0] is arbitrary; perhaps print all
dff50e09 180 }
7fb2f650
FCE
181 else
182 {
183 assert (second->locations.size() >= 1);
184 second->locations[0]->print(tmps); // XXX: [0] is less arbitrary here, but still ...
185 }
186 string pp = tmps.str();
16442b90
FCE
187
188 // Now duplicate-eliminate. An alias may have expanded to
189 // several actual derived probe points, but we only want to
190 // print the alias head name once.
191 if (seen.find (pp) == seen.end())
192 {
d4e35ac8 193 o << pp;
223f5b6b 194 // Print the locals for -L mode only
e2086848 195 if (s.unoptimized) {
223f5b6b
JS
196 for (unsigned j=0; j<p->locals.size(); j++)
197 {
198 o << " ";
199 vardecl* v = p->locals[j];
200 v->printsig (o);
201 }
e2086848
WH
202 // Print arguments of probe if there
203 p->printargs(o);
204 }
223f5b6b 205 o << endl;
16442b90
FCE
206 seen.insert (pp);
207 }
9ba8c134 208 }
1b78aef5 209 }
16442b90 210 else
1b78aef5 211 {
16442b90
FCE
212 if (s.embeds.size() > 0)
213 o << "# global embedded code" << endl;
214 for (unsigned i=0; i<s.embeds.size(); i++)
1b78aef5 215 {
f76427a2 216 if (pending_interrupts) return;
16442b90
FCE
217 embeddedcode* ec = s.embeds[i];
218 ec->print (o);
219 o << endl;
220 }
dff50e09 221
16442b90
FCE
222 if (s.globals.size() > 0)
223 o << "# globals" << endl;
224 for (unsigned i=0; i<s.globals.size(); i++)
1b78aef5 225 {
f76427a2 226 if (pending_interrupts) return;
16442b90
FCE
227 vardecl* v = s.globals[i];
228 v->printsig (o);
229 if (s.verbose && v->init)
230 {
231 o << " = ";
232 v->init->print(o);
233 }
234 o << endl;
235 }
dff50e09 236
16442b90
FCE
237 if (s.functions.size() > 0)
238 o << "# functions" << endl;
f76427a2 239 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
1b78aef5 240 {
f76427a2
FCE
241 if (pending_interrupts) return;
242 functiondecl* f = it->second;
16442b90
FCE
243 f->printsig (o);
244 o << endl;
245 if (f->locals.size() > 0)
246 o << " # locals" << endl;
247 for (unsigned j=0; j<f->locals.size(); j++)
248 {
249 vardecl* v = f->locals[j];
250 o << " ";
251 v->printsig (o);
252 o << endl;
253 }
254 if (s.verbose)
255 {
256 f->body->print (o);
257 o << endl;
258 }
259 }
dff50e09 260
16442b90
FCE
261 if (s.probes.size() > 0)
262 o << "# probes" << endl;
263 for (unsigned i=0; i<s.probes.size(); i++)
1b78aef5 264 {
f76427a2 265 if (pending_interrupts) return;
16442b90
FCE
266 derived_probe* p = s.probes[i];
267 p->printsig (o);
268 o << endl;
269 if (p->locals.size() > 0)
270 o << " # locals" << endl;
271 for (unsigned j=0; j<p->locals.size(); j++)
272 {
273 vardecl* v = p->locals[j];
274 o << " ";
275 v->printsig (o);
276 o << endl;
277 }
278 if (s.verbose)
279 {
280 p->body->print (o);
281 o << endl;
282 }
283 }
284 }
277f2b79 285}
1b78aef5 286
49abf162
FCE
287
288int pending_interrupts;
289
290extern "C"
82737bef 291void handle_interrupt (int sig)
49abf162 292{
4cc40e82 293 kill_stap_spawn(sig);
49abf162 294 pending_interrupts ++;
4cc40e82 295 if (pending_interrupts > 1) // XXX: should be configurable? time-based?
49abf162
FCE
296 {
297 char msg[] = "Too many interrupts received, exiting.\n";
298 int rc = write (2, msg, sizeof(msg)-1);
9ceec314 299 if (rc) {/* Do nothing; we don't care if our last gasp went out. */ ;}
49abf162
FCE
300 _exit (1);
301 }
302}
303
304
3972b443
DS
305void
306setup_signals (sighandler_t handler)
307{
308 struct sigaction sa;
309
310 sa.sa_handler = handler;
311 sigemptyset (&sa.sa_mask);
312 if (handler != SIG_IGN)
313 {
314 sigaddset (&sa.sa_mask, SIGHUP);
315 sigaddset (&sa.sa_mask, SIGPIPE);
316 sigaddset (&sa.sa_mask, SIGINT);
317 sigaddset (&sa.sa_mask, SIGTERM);
318 }
4cc40e82 319 sa.sa_flags = SA_RESTART;
3972b443
DS
320
321 sigaction (SIGHUP, &sa, NULL);
322 sigaction (SIGPIPE, &sa, NULL);
323 sigaction (SIGINT, &sa, NULL);
324 sigaction (SIGTERM, &sa, NULL);
325}
326
4d0a3330
KS
327void
328setup_kernel_release (systemtap_session &s, const char* kstr) {
329 if (kstr[0] == '/') // fully specified path
330 {
331 s.kernel_build_tree = kstr;
332 string version_file_name = s.kernel_build_tree + "/include/config/kernel.release";
333 // The file include/config/kernel.release within the
334 // build tree is used to pull out the version information
335 ifstream version_file (version_file_name.c_str());
336 if (version_file.fail ())
337 {
338 cerr << "Missing " << version_file_name << endl;
339 exit(1);
340 }
341 else
342 {
343 char c;
344 s.kernel_release = "";
345 while (version_file.get(c) && c != '\n')
346 s.kernel_release.push_back(c);
347 }
348 }
349 else
350 {
351 s.kernel_release = string (kstr);
352 s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
353 }
354}
3972b443 355
2b066ec1
FCE
356int
357main (int argc, char * const argv [])
358{
2b066ec1
FCE
359 string cmdline_script; // -e PROGRAM
360 string script_file; // FILE
361 bool have_script = false;
fc52ef5b 362 bool save_module = false;
f4b28491
FCE
363
364 // Initialize defaults
365 systemtap_session s;
366 struct utsname buf;
367 (void) uname (& buf);
368 s.kernel_release = string (buf.release);
b5e66ada
FCE
369 s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
370
44ce8ed5 371 s.architecture = string (buf.machine);
e0b4e89d 372 for (unsigned i=0; i<5; i++) s.perpass_verbose[i]=0;
a9e8f7e0 373 s.timing = false;
377b8831 374 s.guru_mode = false;
16d8de1b 375 s.bulk_mode = false;
cbfbbf69 376 s.unoptimized = false;
a9e8f7e0 377 s.suppress_warnings = false;
16442b90 378 s.listing_mode = false;
44f75386
FCE
379
380#ifdef ENABLE_PROLOGUES
381 s.prologue_searching = true;
382#else
383 s.prologue_searching = false;
384#endif
385
16d8de1b 386 s.buffer_size = 0;
f4b28491 387 s.last_pass = 5;
ae24723e 388 s.module_name = "stap_" + stringify(getpid());
de0db58a 389 s.stapconf_name = "stapconf_" + stringify(getpid()) + ".h";
08c68653 390 s.output_file = ""; // -o FILE
f4b28491 391 s.keep_tmpdir = false;
4c5ff1bb
MH
392 s.cmd = "";
393 s.target_pid = 0;
f272aacc 394 s.merge=true;
47dd066d 395 s.perfmon=0;
f1bad60c 396 s.symtab = false;
1b78aef5 397 s.use_cache = true;
c3a3c0c9 398 s.tapset_compile_coverage = false;
12dc24bc 399 s.need_uprobes = false;
5f0a03a6
JK
400 s.consult_symtab = false;
401 s.ignore_vmlinux = false;
402 s.ignore_dwarf = false;
2fa2a091 403 s.load_only = false;
28f569c2 404 s.skip_badvars = false;
24cb178f 405
2035bcd4
DB
406 // Location of our signing certificate.
407 // If we're root, use the database in SYSCONFDIR, otherwise
408 // use the one in our $HOME directory. */
409 if (geteuid() == 0)
410 s.cert_db_path = SYSCONFDIR "/systemtap/ssl/server";
411 else
412 s.cert_db_path = getenv("HOME") + string ("/.systemtap/ssl/server");
413
24cb178f 414 const char* s_p = getenv ("SYSTEMTAP_TAPSET");
dff50e09 415 if (s_p != NULL)
ec819dc3 416 {
24cb178f 417 s.include_path.push_back (s_p);
ec819dc3 418 }
24cb178f 419 else
ec819dc3 420 {
24cb178f 421 s.include_path.push_back (string(PKGDATADIR) + "/tapset");
ec819dc3 422 }
24cb178f
FCE
423
424 const char* s_r = getenv ("SYSTEMTAP_RUNTIME");
425 if (s_r != NULL)
426 s.runtime_path = s_r;
427 else
428 s.runtime_path = string(PKGDATADIR) + "/runtime";
f4b28491 429
1b78aef5
DS
430 const char* s_d = getenv ("SYSTEMTAP_DIR");
431 if (s_d != NULL)
432 s.data_path = s_d;
433 else
434 s.data_path = get_home_directory() + string("/.systemtap");
435 if (create_dir(s.data_path.c_str()) == 1)
436 {
437 const char* e = strerror (errno);
f4d5049b
FCE
438 if (! s.suppress_warnings)
439 cerr << "Warning: failed to create systemtap data directory (\""
440 << s.data_path << "\"): " << e
441 << ", disabling cache support." << endl;
1b78aef5
DS
442 s.use_cache = false;
443 }
444
445 if (s.use_cache)
446 {
447 s.cache_path = s.data_path + "/cache";
448 if (create_dir(s.cache_path.c_str()) == 1)
449 {
450 const char* e = strerror (errno);
f4d5049b
FCE
451 if (! s.suppress_warnings)
452 cerr << "Warning: failed to create cache directory (\""
453 << s.cache_path << "\"): " << e
454 << ", disabling cache support." << endl;
1b78aef5
DS
455 s.use_cache = false;
456 }
457 }
458
c3a3c0c9
WC
459 const char* s_tc = getenv ("SYSTEMTAP_COVERAGE");
460 if (s_tc != NULL)
461 s.tapset_compile_coverage = true;
462
755cdd9b
KS
463 const char* s_kr = getenv ("SYSTEMTAP_RELEASE");
464 if (s_kr != NULL) {
4d0a3330 465 setup_kernel_release(s, s_kr);
755cdd9b
KS
466 }
467
468
2b066ec1
FCE
469 while (true)
470 {
5f0a03a6 471 int long_opt;
877bbb20 472 char * num_endptr;
5f0a03a6
JK
473#define LONG_OPT_KELF 1
474#define LONG_OPT_KMAP 2
475#define LONG_OPT_IGNORE_VMLINUX 3
476#define LONG_OPT_IGNORE_DWARF 4
e0b4e89d 477#define LONG_OPT_VERBOSE_PASS 5
3bd0d4df 478#define LONG_OPT_SKIP_BADVARS 6
a9e8f7e0 479 // NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
5f0a03a6
JK
480 static struct option long_options[] = {
481 { "kelf", 0, &long_opt, LONG_OPT_KELF },
482 { "kmap", 2, &long_opt, LONG_OPT_KMAP },
483 { "ignore-vmlinux", 0, &long_opt, LONG_OPT_IGNORE_VMLINUX },
484 { "ignore-dwarf", 0, &long_opt, LONG_OPT_IGNORE_DWARF },
3bd0d4df 485 { "skip-badvars", 0, &long_opt, LONG_OPT_SKIP_BADVARS },
e0b4e89d 486 { "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS },
5f0a03a6
JK
487 { NULL, 0, NULL, 0 }
488 };
701c41be 489 int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:",
5f0a03a6 490 long_options, NULL);
2b066ec1
FCE
491 if (grc < 0)
492 break;
493 switch (grc)
494 {
c0de7a8d
FCE
495 case 'V':
496 version ();
497 exit (0);
498
f272aacc
LG
499 case 'M':
500 s.merge = false;
501 break;
502
bd2b1e68 503 case 'v':
e0b4e89d
FCE
504 for (unsigned i=0; i<5; i++)
505 s.perpass_verbose[i] ++;
bd2b1e68
GH
506 break;
507
4b17d6af 508 case 't':
a9e8f7e0
FCE
509 s.timing = true;
510 break;
511
512 case 'w':
513 s.suppress_warnings = true;
4b17d6af
WC
514 break;
515
2b066ec1 516 case 'p':
16442b90
FCE
517 if (s.listing_mode)
518 {
519 cerr << "Listing (-l) mode implies pass 2." << endl;
520 usage (s, 1);
521 }
877bbb20
SW
522 s.last_pass = (int)strtoul(optarg, &num_endptr, 10);
523 if (*num_endptr != '\0' || s.last_pass < 1 || s.last_pass > 5)
2b066ec1 524 {
277c1957
DS
525 cerr << "Invalid pass number (should be 1-5)." << endl;
526 usage (s, 1);
2b066ec1
FCE
527 }
528 break;
529
530 case 'I':
f4b28491 531 s.include_path.push_back (string (optarg));
2b066ec1
FCE
532 break;
533
a8368458 534 case 'd':
1a0dbc5a 535 s.unwindsym_modules.insert (string (optarg));
a8368458
FCE
536 break;
537
2b066ec1
FCE
538 case 'e':
539 if (have_script)
277c1957
DS
540 {
541 cerr << "Only one script can be given on the command line."
542 << endl;
543 usage (s, 1);
544 }
2b066ec1
FCE
545 cmdline_script = string (optarg);
546 have_script = true;
547 break;
548
549 case 'o':
08c68653 550 s.output_file = string (optarg);
2b066ec1
FCE
551 break;
552
f4b28491
FCE
553 case 'R':
554 s.runtime_path = string (optarg);
555 break;
556
557 case 'm':
558 s.module_name = string (optarg);
fc52ef5b 559 save_module = true;
3b942fed
DS
560 {
561 string::size_type len = s.module_name.length();
562
563 // If the module name ends with '.ko', chop it off since
564 // modutils doesn't like modules named 'foo.ko.ko'.
565 if (len > 3 && s.module_name.substr(len - 3, 3) == ".ko")
566 {
567 s.module_name.erase(len - 3);
568 len -= 3;
569 cerr << "Truncating module name to '" << s.module_name
570 << "'" << endl;
571 }
572
573 // Make sure an empty module name wasn't specified (-m "")
574 if (len == 0)
575 {
576 cerr << "Module name cannot be empty." << endl;
577 usage (s, 1);
578 }
579
580 // Make sure the module name is only composed of the
581 // following chars: [_a-zA-Z0-9]
582 const string identchars("_" "abcdefghijklmnopqrstuvwxyz"
583 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789");
584 if (s.module_name.find_first_not_of(identchars) != string::npos)
585 {
586 cerr << "Invalid module name (must only be composed of"
587 " characters [_a-zA-Z0-9])." << endl;
588 usage (s, 1);
589 }
98aab489
DS
590
591 // Make sure module name isn't too long.
592 if (s.module_name.size() >= (MODULE_NAME_LEN - 1))
593 {
594 s.module_name.resize(MODULE_NAME_LEN - 1);
595 cerr << "Truncating module name to '" << s.module_name
596 << "'" << endl;
597 }
3b942fed
DS
598 }
599
1b78aef5 600 s.use_cache = false;
f4b28491
FCE
601 break;
602
603 case 'r':
4d0a3330 604 setup_kernel_release(s, optarg);
f4b28491
FCE
605 break;
606
607 case 'k':
608 s.keep_tmpdir = true;
f53a92f9 609 s.use_cache = false; /* User wants to keep a usable build tree. */
f4b28491
FCE
610 break;
611
377b8831
FCE
612 case 'g':
613 s.guru_mode = true;
614 break;
615
44f75386
FCE
616 case 'P':
617 s.prologue_searching = true;
618 break;
619
16d8de1b
TZ
620 case 'b':
621 s.bulk_mode = true;
16d8de1b
TZ
622 break;
623
cbfbbf69
FCE
624 case 'u':
625 s.unoptimized = true;
626 break;
627
16d8de1b
TZ
628 case 's':
629 s.buffer_size = atoi (optarg);
453b58ed 630 if (s.buffer_size < 1 || s.buffer_size > 4095)
16d8de1b 631 {
453b58ed 632 cerr << "Invalid buffer size (should be 1-4095)." << endl;
277c1957 633 usage (s, 1);
16d8de1b
TZ
634 }
635 break;
636
4c5ff1bb
MH
637 case 'c':
638 s.cmd = string (optarg);
639 break;
640
641 case 'x':
642 s.target_pid = atoi(optarg);
643 break;
644
ed10c639
FCE
645 case 'D':
646 s.macros.push_back (string (optarg));
647 break;
648
701c41be
MH
649 case 'S':
650 s.size_option = string (optarg);
651 break;
652
c3a3c0c9
WC
653 case 'q':
654 s.tapset_compile_coverage = true;
655 break;
656
2b066ec1 657 case 'h':
277c1957
DS
658 usage (s, 0);
659 break;
660
d4e35ac8 661 case 'L':
1044139f 662 s.unoptimized = true; // This causes retention of variables for listing_mode
d4e35ac8 663
16442b90 664 case 'l':
4bd48e4b 665 s.suppress_warnings = true;
16442b90
FCE
666 s.listing_mode = true;
667 s.last_pass = 2;
668 if (have_script)
669 {
670 cerr << "Only one script can be given on the command line."
671 << endl;
672 usage (s, 1);
673 }
674 cmdline_script = string("probe ") + string(optarg) + " {}";
675 have_script = true;
676 break;
677
2fa2a091
NT
678 case 'F':
679 s.load_only = true;
680 break;
681
5f0a03a6
JK
682 case 0:
683 switch (long_opt)
684 {
685 case LONG_OPT_KELF:
686 s.consult_symtab = true;
687 break;
688 case LONG_OPT_KMAP:
689 // Leave s.consult_symtab unset for now, to ease error checking.
690 if (!s.kernel_symtab_path.empty())
691 {
692 cerr << "You can't specify multiple --kmap options." << endl;
693 usage(s, 1);
694 }
695 if (optarg)
696 s.kernel_symtab_path = optarg;
697 else
698#define PATH_TBD string("__TBD__")
699 s.kernel_symtab_path = PATH_TBD;
700 break;
701 case LONG_OPT_IGNORE_VMLINUX:
702 s.ignore_vmlinux = true;
703 break;
704 case LONG_OPT_IGNORE_DWARF:
705 s.ignore_dwarf = true;
706 break;
e0b4e89d
FCE
707 case LONG_OPT_VERBOSE_PASS:
708 {
709 bool ok = true;
710 if (strlen(optarg) < 1 || strlen(optarg) > 5)
711 ok = false;
712 if (ok)
b688229d 713 for (unsigned i=0; i<strlen(optarg); i++)
e0b4e89d
FCE
714 if (isdigit (optarg[i]))
715 s.perpass_verbose[i] += optarg[i]-'0';
716 else
717 ok = false;
718
719 if (! ok)
720 {
721 cerr << "Invalid --vp argument: it takes 1 to 5 digits." << endl;
722 usage (s, 1);
723 }
724 // NB: we don't do this: s.last_pass = strlen(optarg);
725 break;
726 }
3bd0d4df
RA
727 case LONG_OPT_SKIP_BADVARS:
728 s.skip_badvars = true;
729 break;
5f0a03a6
JK
730 default:
731 cerr << "Internal error parsing command arguments." << endl;
732 usage(s, 1);
733 }
734 break;
735
2b066ec1 736 default:
277c1957
DS
737 usage (s, 1);
738 break;
2b066ec1
FCE
739 }
740 }
741
f272aacc
LG
742 if(!s.bulk_mode && !s.merge)
743 {
744 cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
277c1957 745 usage (s, 1);
f272aacc
LG
746 }
747
748 if(!s.output_file.empty() && s.bulk_mode && !s.merge)
749 {
750 cerr << "You can't specify -M, -b and -o options together." <<endl;
277c1957 751 usage (s, 1);
f272aacc
LG
752 }
753
54dec22d
DS
754 if((s.cmd != "") && (s.target_pid))
755 {
756 cerr << "You can't specify -c and -x options together." <<endl;
757 usage (s, 1);
758 }
759
5f0a03a6
JK
760 if (!s.kernel_symtab_path.empty())
761 {
762 if (s.consult_symtab)
763 {
764 cerr << "You can't specify --kelf and --kmap together." << endl;
765 usage (s, 1);
766 }
767 s.consult_symtab = true;
768 if (s.kernel_symtab_path == PATH_TBD)
769 s.kernel_symtab_path = string("/boot/System.map-") + s.kernel_release;
770 }
771
b5e66ada
FCE
772 // Warn in case the target kernel release doesn't match the running one.
773 if (s.last_pass > 4 &&
774 (string(buf.release) != s.kernel_release ||
775 string(buf.machine) != s.architecture))
776 {
777 if(! s.suppress_warnings)
778 cerr << "WARNING: kernel release/architecture mismatch with host forces last-pass 4." << endl;
779 s.last_pass = 4;
780 }
ea3f75ae 781
2b066ec1
FCE
782 for (int i = optind; i < argc; i++)
783 {
784 if (! have_script)
785 {
786 script_file = string (argv[i]);
787 have_script = true;
788 }
789 else
f4b28491 790 s.args.push_back (string (argv[i]));
2b066ec1
FCE
791 }
792
793 // need a user file
794 if (! have_script)
277c1957
DS
795 {
796 cerr << "A script must be specified." << endl;
797 usage(s, 1);
798 }
f4b28491 799
a929fd0f
Z
800 // translate path of runtime to absolute path
801 if (s.runtime_path[0] != '/')
802 {
803 char cwd[PATH_MAX];
804 if (getcwd(cwd, sizeof(cwd)))
805 {
806 s.runtime_path = string(cwd) + "/" + s.runtime_path;
807 }
808 }
809
f4b28491 810 int rc = 0;
c31df222
FCE
811
812 // PASS 0: setting up
813 s.verbose = s.perpass_verbose[0];
2b066ec1 814
d0a7f5a9
FCE
815 // For PR1477, we used to override $PATH and $LC_ALL and other stuff
816 // here. We seem to use complete pathnames in
817 // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
818 // it interferes with util.cxx:find_executable(), used for $PATH
819 // resolution.
861c2f28 820
197a4d62
JS
821 s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
822
2b066ec1 823 // arguments parsed; get down to business
72d18b98 824 if (s.verbose > 1)
c0e526f0
FCE
825 {
826 version ();
827 clog << "Session arch: " << s.architecture
828 << " release: " << s.kernel_release
829 << endl;
830 }
2b066ec1 831
f4b28491
FCE
832 // Create a temporary directory to build within.
833 // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
834 {
c72dc86c 835 const char* tmpdir_env = getenv("TMPDIR");
ea8ea02c
FCE
836 if (! tmpdir_env)
837 tmpdir_env = "/tmp";
dff50e09 838
ea8ea02c
FCE
839 string stapdir = "/stapXXXXXX";
840 string tmpdirt = tmpdir_env + stapdir;
533af4f0 841 mode_t mask = umask(0);
ea8ea02c 842 const char* tmpdir = mkdtemp((char *)tmpdirt.c_str());
533af4f0 843 umask(mask);
f4b28491
FCE
844 if (! tmpdir)
845 {
846 const char* e = strerror (errno);
ea8ea02c
FCE
847 cerr << "ERROR: cannot create temporary directory (\"" << tmpdirt << "\"): " << e << endl;
848 exit (1); // die
f4b28491
FCE
849 }
850 else
851 s.tmpdir = tmpdir;
0d49d7bc 852
b0ee93c4 853 if (s.verbose>1)
0d49d7bc 854 clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491 855 }
2b066ec1 856
1b78aef5
DS
857 // Create the name of the C source file within the temporary
858 // directory.
859 s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
860
dff50e09 861 // Set up our handler to catch routine signals, to allow clean
49abf162 862 // and reasonably timely exit.
3972b443 863 setup_signals(&handle_interrupt);
49abf162 864
5ee1c56b
FCE
865 struct tms tms_before;
866 times (& tms_before);
1d738eed
FCE
867 struct timeval tv_before;
868 gettimeofday (&tv_before, NULL);
2b066ec1
FCE
869
870 // PASS 1a: PARSING USER SCRIPT
f59e98c4
FCE
871
872 struct stat user_file_stat;
873 int user_file_stat_rc = -1;
874
69c68955 875 if (script_file == "-")
129be0ac
FCE
876 {
877 s.user_file = parser::parse (s, cin, s.guru_mode);
878 user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
879 }
69c68955 880 else if (script_file != "")
f59e98c4
FCE
881 {
882 s.user_file = parser::parse (s, script_file, s.guru_mode);
883 user_file_stat_rc = stat (script_file.c_str(), & user_file_stat);
884 }
2b066ec1
FCE
885 else
886 {
887 istringstream ii (cmdline_script);
177a8ead 888 s.user_file = parser::parse (s, ii, s.guru_mode);
2b066ec1
FCE
889 }
890 if (s.user_file == 0)
891 // syntax errors already printed
892 rc ++;
377b8831 893
5519d363 894 // Construct arch / kernel-versioning search path
377b8831 895 vector<string> version_suffixes;
6f9f33e2 896 string kvr = s.kernel_release;
5519d363
KS
897 const string& arch = s.architecture;
898 // add full kernel-version-release (2.6.NN-FOOBAR) + arch
899 version_suffixes.push_back ("/" + kvr + "/" + arch);
377b8831 900 version_suffixes.push_back ("/" + kvr);
5519d363 901 // add kernel version (2.6.NN) + arch
197a4d62
JS
902 if (kvr != s.kernel_base_release) {
903 kvr = s.kernel_base_release;
6f9f33e2
JS
904 version_suffixes.push_back ("/" + kvr + "/" + arch);
905 version_suffixes.push_back ("/" + kvr);
5519d363
KS
906 }
907 // add kernel family (2.6) + arch
6f9f33e2
JS
908 string::size_type dot1_index = kvr.find ('.');
909 string::size_type dot2_index = kvr.rfind ('.');
910 while (dot2_index > dot1_index && dot2_index != string::npos) {
911 kvr.erase(dot2_index);
912 version_suffixes.push_back ("/" + kvr + "/" + arch);
913 version_suffixes.push_back ("/" + kvr);
914 dot2_index = kvr.rfind ('.');
5519d363
KS
915 }
916 // add architecture search path
917 version_suffixes.push_back("/" + arch);
377b8831
FCE
918 // add empty string as last element
919 version_suffixes.push_back ("");
2b066ec1
FCE
920
921 // PASS 1b: PARSING LIBRARY SCRIPTS
f4b28491 922 for (unsigned i=0; i<s.include_path.size(); i++)
2b066ec1 923 {
377b8831
FCE
924 // now iterate upon it
925 for (unsigned k=0; k<version_suffixes.size(); k++)
2b066ec1 926 {
377b8831
FCE
927 glob_t globbuf;
928 string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
929 int r = glob(dir.c_str (), 0, NULL, & globbuf);
930 if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
2b066ec1 931 rc ++;
377b8831
FCE
932 // GLOB_NOMATCH is acceptable
933
c4a94c1a 934 if (s.verbose>1 && globbuf.gl_pathc > 0)
377b8831 935 clog << "Searched '" << dir << "', "
c4a94c1a 936 << "found " << globbuf.gl_pathc << endl;
2b066ec1 937
377b8831
FCE
938 for (unsigned j=0; j<globbuf.gl_pathc; j++)
939 {
49abf162
FCE
940 if (pending_interrupts)
941 break;
942
943 // XXX: privilege only for /usr/share/systemtap?
177a8ead 944 stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true);
377b8831
FCE
945 if (f == 0)
946 rc ++;
947 else
24cb178f 948 s.library_files.push_back (f);
f59e98c4
FCE
949
950 struct stat tapset_file_stat;
951 int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
952 if (stat_rc == 0 && user_file_stat_rc == 0 &&
953 user_file_stat.st_dev == tapset_file_stat.st_dev &&
954 user_file_stat.st_ino == tapset_file_stat.st_ino)
955 {
129be0ac
FCE
956 clog << "usage error: tapset file '" << globbuf.gl_pathv[j]
957 << "' cannot be run directly as a session script." << endl;
f59e98c4
FCE
958 rc ++;
959 }
960
377b8831 961 }
d54d4661 962
377b8831
FCE
963 globfree (& globbuf);
964 }
2b066ec1
FCE
965 }
966
f4b28491 967 if (rc == 0 && s.last_pass == 1)
2b066ec1 968 {
f4b28491
FCE
969 cout << "# parse tree dump" << endl;
970 s.user_file->print (cout);
971 cout << endl;
ae56fddd
FCE
972 if (s.verbose)
973 for (unsigned i=0; i<s.library_files.size(); i++)
974 {
975 s.library_files[i]->print (cout);
976 cout << endl;
977 }
2b066ec1
FCE
978 }
979
5ee1c56b
FCE
980 struct tms tms_after;
981 times (& tms_after);
982 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
1d738eed
FCE
983 struct timeval tv_after;
984 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
985
986#define TIMESPRINT \
987 (tms_after.tms_cutime + tms_after.tms_utime \
1d738eed 988 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
5ee1c56b 989 << (tms_after.tms_cstime + tms_after.tms_stime \
1d738eed
FCE
990 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
991 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
992 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
5ee1c56b 993
eaf134e7 994 // syntax errors, if any, are already printed
5ee1c56b
FCE
995 if (s.verbose)
996 {
997 clog << "Pass 1: parsed user script and "
998 << s.library_files.size()
999 << " library script(s) in "
1000 << TIMESPRINT
1001 << endl;
1002 }
0d49d7bc 1003
708ce1f3 1004 if (rc && !s.listing_mode)
2cfb0e46 1005 cerr << "Pass 1: parse failed. "
c3157bcd 1006 << "Try again with another '--vp 1' option."
2cfb0e46
FCE
1007 << endl;
1008
49abf162 1009 if (rc || s.last_pass == 1 || pending_interrupts) goto cleanup;
f4b28491 1010
5ee1c56b 1011 times (& tms_before);
1d738eed 1012 gettimeofday (&tv_before, NULL);
5ee1c56b 1013
2b066ec1 1014 // PASS 2: ELABORATION
e0b4e89d 1015 s.verbose = s.perpass_verbose[1];
0d49d7bc 1016 rc = semantic_pass (s);
f4b28491 1017
16442b90 1018 if (s.listing_mode || (rc == 0 && s.last_pass == 2))
1b78aef5 1019 printscript(s, cout);
2b066ec1 1020
5ee1c56b 1021 times (& tms_after);
1d738eed
FCE
1022 gettimeofday (&tv_after, NULL);
1023
b0ee93c4 1024 if (s.verbose) clog << "Pass 2: analyzed script: "
0d49d7bc
FCE
1025 << s.probes.size() << " probe(s), "
1026 << s.functions.size() << " function(s), "
b20febf3 1027 << s.embeds.size() << " embed(s), "
5ee1c56b
FCE
1028 << s.globals.size() << " global(s) in "
1029 << TIMESPRINT
1030 << endl;
0d49d7bc 1031
708ce1f3 1032 if (rc && !s.listing_mode)
377b8831 1033 cerr << "Pass 2: analysis failed. "
c3157bcd 1034 << "Try again with another '--vp 01' option."
2cfb0e46 1035 << endl;
1b78aef5
DS
1036 // Generate hash. There isn't any point in generating the hash
1037 // if last_pass is 2, since we'll quit before using it.
1038 else if (s.last_pass != 2 && s.use_cache)
1039 {
1040 ostringstream o;
1041 unsigned saved_verbose;
1b78aef5 1042
9abec538
FCE
1043 {
1044 // Make sure we're in verbose mode, so that printscript()
1045 // will output function/probe bodies.
1046 saved_verbose = s.verbose;
1047 s.verbose = 3;
1048 printscript(s, o); // Print script to 'o'
1049 s.verbose = saved_verbose;
1050 }
1b78aef5
DS
1051
1052 // Generate hash
1053 find_hash (s, o.str());
1054
1055 // See if we can use cached source/module.
1056 if (get_from_cache(s))
1057 {
db3a383b
JK
1058 // If our last pass isn't 5, we're done (since passes 3 and
1059 // 4 just generate what we just pulled out of the cache).
49abf162 1060 if (s.last_pass < 5 || pending_interrupts) goto cleanup;
1b78aef5 1061
db3a383b
JK
1062 // Short-circuit to pass 5.
1063 goto pass_5;
1b78aef5
DS
1064 }
1065 }
377b8831 1066
16442b90 1067 if (rc || s.listing_mode || s.last_pass == 2 || pending_interrupts) goto cleanup;
f4b28491 1068
2b066ec1 1069 // PASS 3: TRANSLATION
e0b4e89d 1070 s.verbose = s.perpass_verbose[2];
5ee1c56b 1071 times (& tms_before);
1d738eed
FCE
1072 gettimeofday (&tv_before, NULL);
1073
0d49d7bc 1074 rc = translate_pass (s);
f4b28491
FCE
1075
1076 if (rc == 0 && s.last_pass == 3)
1077 {
1078 ifstream i (s.translated_source.c_str());
1079 cout << i.rdbuf();
1080 }
0d49d7bc 1081
5ee1c56b 1082 times (& tms_after);
1d738eed 1083 gettimeofday (&tv_after, NULL);
5ee1c56b 1084
0d49d7bc
FCE
1085 if (s.verbose) clog << "Pass 3: translated to C into \""
1086 << s.translated_source
5ee1c56b
FCE
1087 << "\" in "
1088 << TIMESPRINT
1089 << endl;
0d49d7bc 1090
377b8831 1091 if (rc)
2cfb0e46 1092 cerr << "Pass 3: translation failed. "
c3157bcd 1093 << "Try again with another '--vp 001' option."
2cfb0e46 1094 << endl;
377b8831 1095
49abf162 1096 if (rc || s.last_pass == 3 || pending_interrupts) goto cleanup;
d54d4661 1097
f4b28491 1098 // PASS 4: COMPILATION
e0b4e89d 1099 s.verbose = s.perpass_verbose[3];
5ee1c56b 1100 times (& tms_before);
1d738eed 1101 gettimeofday (&tv_before, NULL);
0d49d7bc 1102 rc = compile_pass (s);
9abec538
FCE
1103
1104 if (rc == 0 && s.last_pass == 4)
422dc4e1
FCE
1105 {
1106 cout << ((s.hash_path == "") ? (s.module_name + string(".ko")) : s.hash_path);
1107 cout << endl;
1108 }
9abec538 1109
5ee1c56b 1110 times (& tms_after);
1d738eed 1111 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
1112
1113 if (s.verbose) clog << "Pass 4: compiled C into \""
1114 << s.module_name << ".ko"
1115 << "\" in "
1116 << TIMESPRINT
1117 << endl;
f4b28491 1118
eaf134e7
FCE
1119 if (rc)
1120 cerr << "Pass 4: compilation failed. "
c3157bcd 1121 << "Try again with another '--vp 0001' option."
2cfb0e46 1122 << endl;
fc52ef5b 1123 else
1b78aef5 1124 {
06c7e057 1125 // Update cache. Cache cleaning is kicked off at the end of this function.
fc52ef5b 1126 if (s.use_cache)
f4d5049b 1127 add_to_cache(s);
fc52ef5b 1128
f4d5049b
FCE
1129 // We may need to save the module in $CWD if the cache was
1130 // inaccessible for some reason.
1131 if (! s.use_cache && s.last_pass == 4)
1132 save_module = true;
1133
fc52ef5b 1134 // Copy module to the current directory.
49abf162 1135 if (save_module && !pending_interrupts)
fc52ef5b
DS
1136 {
1137 string module_src_path = s.tmpdir + "/" + s.module_name + ".ko";
1138 string module_dest_path = s.module_name + ".ko";
1139
1140 if (s.verbose > 1)
1141 clog << "Copying " << module_src_path << " to "
1142 << module_dest_path << endl;
1143 if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
1144 cerr << "Copy failed (\"" << module_src_path << "\" to \""
1145 << module_dest_path << "\"): " << strerror(errno) << endl;
2035bcd4
DB
1146
1147#if HAVE_NSS
1148 // Save the signature as well.
1149 assert (! s.cert_db_path.empty());
1150 module_src_path += ".sgn";
1151 module_dest_path += ".sgn";
1152
1153 if (s.verbose > 1)
1154 clog << "Copying " << module_src_path << " to "
1155 << module_dest_path << endl;
1156 if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
1157 cerr << "Copy failed (\"" << module_src_path << "\" to \""
1158 << module_dest_path << "\"): " << strerror(errno) << endl;
1159#endif
fc52ef5b 1160 }
1b78aef5 1161 }
eaf134e7 1162
49abf162 1163 if (rc || s.last_pass == 4 || pending_interrupts) goto cleanup;
f4b28491 1164
9abec538 1165
0d49d7bc 1166 // PASS 5: RUN
1b78aef5 1167pass_5:
e0b4e89d 1168 s.verbose = s.perpass_verbose[4];
5ee1c56b 1169 times (& tms_before);
1d738eed 1170 gettimeofday (&tv_before, NULL);
03d569d3
FCE
1171 // NB: this message is a judgement call. The other passes don't emit
1172 // a "hello, I'm starting" message, but then the others aren't interactive
1173 // and don't take an indefinite amount of time.
1174 if (s.verbose) clog << "Pass 5: starting run." << endl;
0d49d7bc 1175 rc = run_pass (s);
5ee1c56b 1176 times (& tms_after);
1d738eed 1177 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
1178 if (s.verbose) clog << "Pass 5: run completed in "
1179 << TIMESPRINT
1180 << endl;
f4b28491 1181
eaf134e7
FCE
1182 if (rc)
1183 cerr << "Pass 5: run failed. "
c3157bcd 1184 << "Try again with another '--vp 00001' option."
2cfb0e46 1185 << endl;
eaf134e7 1186
0d49d7bc 1187 // if (rc) goto cleanup;
2b066ec1 1188
c31df222 1189 // PASS 6: cleaning up
0d49d7bc 1190 cleanup:
c3a3c0c9
WC
1191
1192 // update the database information
49abf162 1193 if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
1c0b94ef 1194#ifdef HAVE_LIBSQLITE3
c3a3c0c9 1195 update_coverage_db(s);
1c0b94ef
FCE
1196#else
1197 cerr << "Coverage database not available without libsqlite3" << endl;
1198#endif
c3a3c0c9
WC
1199 }
1200
f4b28491
FCE
1201 // Clean up temporary directory. Obviously, be careful with this.
1202 if (s.tmpdir == "")
1203 ; // do nothing
1204 else
1205 {
1206 if (s.keep_tmpdir)
0d49d7bc 1207 clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491
FCE
1208 else
1209 {
3972b443
DS
1210 // Ignore signals while we're deleting the temporary directory.
1211 setup_signals (SIG_IGN);
1212
1213 // Remove the temporary directory.
ce3187ac 1214 string cleanupcmd = "rm -rf ";
f4b28491 1215 cleanupcmd += s.tmpdir;
b0ee93c4 1216 if (s.verbose>1) clog << "Running " << cleanupcmd << endl;
4cc40e82 1217 int status = stap_system (cleanupcmd.c_str());
b0ee93c4 1218 if (status != 0 && s.verbose>1)
d54d4661 1219 clog << "Cleanup command failed, status: " << status << endl;
f4b28491
FCE
1220 }
1221 }
2b066ec1 1222
49abf162 1223 return (rc||pending_interrupts) ? EXIT_FAILURE : EXIT_SUCCESS;
2b066ec1 1224}
73267b89
JS
1225
1226/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.236256 seconds and 5 git commands to generate.