]> sourceware.org Git - systemtap.git/blame - main.cxx
vfs.stp:
[systemtap.git] / main.cxx
CommitLineData
f4b28491 1// systemtap translator/driver
213bee8f 2// Copyright (C) 2005-2006 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"
2b066ec1
FCE
17
18#include <iostream>
19#include <fstream>
20#include <sstream>
f4b28491 21#include <cerrno>
24cb178f 22#include <cstdlib>
2b066ec1
FCE
23
24extern "C" {
25#include <glob.h>
26#include <unistd.h>
f4b28491 27#include <sys/utsname.h>
5ee1c56b 28#include <sys/times.h>
1d738eed 29#include <sys/time.h>
f4b28491 30#include <time.h>
f8949662 31#include <elfutils/libdwfl.h>
2b066ec1
FCE
32}
33
34using namespace std;
35
36
f4b28491 37void
c0de7a8d 38version ()
2b066ec1 39{
d54d4661 40 clog
d04cf5ff 41 << "SystemTap translator/driver "
f4b28491 42 << "(version " << VERSION << " built " << DATE << ")" << endl
f8949662 43 << "(Using " << dwfl_version (NULL) << " libraries.)" << endl
b9b91512 44 << "Copyright (C) 2005-2006 Red Hat, Inc. and others" << endl
f8949662 45 << "This is free software; see the source for copying conditions." << endl;
c0de7a8d
FCE
46}
47
48void
277c1957 49usage (systemtap_session& s, int exitcode)
c0de7a8d
FCE
50{
51 version ();
52 clog
f4b28491 53 << endl
b2d5d95c 54 << "Usage: stap [options] FILE Run script in file."
f4b28491 55 << endl
b2d5d95c 56 << " or: stap [options] - Run script on stdin."
f4b28491 57 << endl
d54d4661 58 << " or: stap [options] -e SCRIPT Run given script."
f4b28491
FCE
59 << endl
60 << endl
c0de7a8d 61 << "Options:" << endl
f4b28491 62 << " -- no more options after this" << endl
b0ee93c4 63 << " -v increase verbosity [" << s.verbose << "]" << endl
c0de7a8d
FCE
64 << " -h show help" << endl
65 << " -V show version" << endl
d5d7c2cc 66 << " -k keep temporary directory" << endl
cbfbbf69 67 << " -u unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl
377b8831 68 << " -g guru mode" << (s.guru_mode ? " [set]" : "") << endl
f12b2552 69 << " -b bulk (relayfs) mode" << (s.bulk_mode ? " [set]" : "") << endl
f272aacc 70 << " -M Don't merge per-cpu files for bulk (relayfs) mode" << (s.merge ? "" : " [set]") << endl
177a8ead
FCE
71 << " -s NUM buffer size in megabytes, instead of "
72 << s.buffer_size << endl
f8949662 73 << " -p NUM stop after pass NUM 1-5, instead of "
177a8ead 74 << s.last_pass << endl
f4b28491
FCE
75 << " (parse, elaborate, translate, compile, run)" << endl
76 << " -I DIR look in DIR for additional .stp script files";
77 if (s.include_path.size() == 0)
0d49d7bc 78 clog << endl;
f4b28491 79 else
24cb178f 80 clog << ", in addition to" << endl;
f4b28491 81 for (unsigned i=0; i<s.include_path.size(); i++)
0d49d7bc
FCE
82 clog << " " << s.include_path[i] << endl;
83 clog
ed10c639 84 << " -D NM=VAL emit macro definition into generated C code" << endl
24cb178f
FCE
85 << " -R DIR look in DIR for runtime, instead of" << endl
86 << " " << s.runtime_path << endl
177a8ead
FCE
87 << " -r RELEASE use kernel RELEASE, instead of "
88 << s.kernel_release << endl
f12b2552
FCE
89 << " -m MODULE set probe module name, instead of "
90 << s.module_name << endl
177a8ead 91 << " -o FILE send output to file, instead of stdout" << endl
f8949662 92 << " -c CMD start the probes, run CMD, and exit when it finishes"
f12b2552 93 << endl
4c5ff1bb 94 << " -x PID sets target() to PID" << endl
4b17d6af 95 << " -t benchmarking timing information generated" << endl
d5d7c2cc 96 ;
d54d4661 97 // -d: dump safety-related external references
2b066ec1 98
277c1957 99 exit (exitcode);
2b066ec1
FCE
100}
101
102
f4b28491
FCE
103// little utility function
104
105template <typename T>
106static string
107stringify(T t)
108{
109 ostringstream s;
110 s << t;
111 return s.str ();
112}
113
114
2b066ec1
FCE
115int
116main (int argc, char * const argv [])
117{
2b066ec1
FCE
118 string cmdline_script; // -e PROGRAM
119 string script_file; // FILE
120 bool have_script = false;
f4b28491
FCE
121
122 // Initialize defaults
123 systemtap_session s;
124 struct utsname buf;
125 (void) uname (& buf);
126 s.kernel_release = string (buf.release);
44ce8ed5 127 s.architecture = string (buf.machine);
b0ee93c4 128 s.verbose = 0;
4b17d6af 129 s.timing = 0;
377b8831 130 s.guru_mode = false;
16d8de1b 131 s.bulk_mode = false;
cbfbbf69 132 s.unoptimized = false;
16d8de1b 133 s.buffer_size = 0;
f4b28491 134 s.last_pass = 5;
ae24723e 135 s.module_name = "stap_" + stringify(getpid());
08c68653 136 s.output_file = ""; // -o FILE
f4b28491 137 s.keep_tmpdir = false;
4c5ff1bb
MH
138 s.cmd = "";
139 s.target_pid = 0;
f272aacc 140 s.merge=true;
24cb178f
FCE
141
142 const char* s_p = getenv ("SYSTEMTAP_TAPSET");
ec819dc3
LG
143 if (s_p != NULL)
144 {
24cb178f 145 s.include_path.push_back (s_p);
ec819dc3
LG
146 s.include_path.push_back (string(s_p) + "/LKET");
147 }
24cb178f 148 else
ec819dc3 149 {
24cb178f 150 s.include_path.push_back (string(PKGDATADIR) + "/tapset");
ec819dc3
LG
151 s.include_path.push_back (string(PKGDATADIR) + "/tapset/LKET");
152 }
24cb178f
FCE
153
154 const char* s_r = getenv ("SYSTEMTAP_RUNTIME");
155 if (s_r != NULL)
156 s.runtime_path = s_r;
157 else
158 s.runtime_path = string(PKGDATADIR) + "/runtime";
f4b28491 159
2b066ec1
FCE
160 while (true)
161 {
f272aacc 162 int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgc:x:D:bs:u");
2b066ec1
FCE
163 if (grc < 0)
164 break;
165 switch (grc)
166 {
c0de7a8d
FCE
167 case 'V':
168 version ();
169 exit (0);
170
f272aacc
LG
171 case 'M':
172 s.merge = false;
173 break;
174
bd2b1e68 175 case 'v':
b0ee93c4 176 s.verbose ++;
bd2b1e68
GH
177 break;
178
4b17d6af
WC
179 case 't':
180 s.timing ++;
181 break;
182
2b066ec1 183 case 'p':
f4b28491
FCE
184 s.last_pass = atoi (optarg);
185 if (s.last_pass < 1 || s.last_pass > 5)
2b066ec1 186 {
277c1957
DS
187 cerr << "Invalid pass number (should be 1-5)." << endl;
188 usage (s, 1);
2b066ec1
FCE
189 }
190 break;
191
192 case 'I':
f4b28491 193 s.include_path.push_back (string (optarg));
2b066ec1
FCE
194 break;
195
196 case 'e':
197 if (have_script)
277c1957
DS
198 {
199 cerr << "Only one script can be given on the command line."
200 << endl;
201 usage (s, 1);
202 }
2b066ec1
FCE
203 cmdline_script = string (optarg);
204 have_script = true;
205 break;
206
207 case 'o':
08c68653 208 s.output_file = string (optarg);
2b066ec1
FCE
209 break;
210
f4b28491
FCE
211 case 'R':
212 s.runtime_path = string (optarg);
213 break;
214
215 case 'm':
216 s.module_name = string (optarg);
217 break;
218
219 case 'r':
220 s.kernel_release = string (optarg);
221 break;
222
223 case 'k':
224 s.keep_tmpdir = true;
225 break;
226
377b8831
FCE
227 case 'g':
228 s.guru_mode = true;
229 break;
230
16d8de1b
TZ
231 case 'b':
232 s.bulk_mode = true;
16d8de1b
TZ
233 break;
234
cbfbbf69
FCE
235 case 'u':
236 s.unoptimized = true;
237 break;
238
16d8de1b
TZ
239 case 's':
240 s.buffer_size = atoi (optarg);
241 if (s.buffer_size < 1 || s.buffer_size > 64)
242 {
277c1957
DS
243 cerr << "Invalid buffer size (should be 1-64)." << endl;
244 usage (s, 1);
16d8de1b
TZ
245 }
246 break;
247
4c5ff1bb
MH
248 case 'c':
249 s.cmd = string (optarg);
250 break;
251
252 case 'x':
253 s.target_pid = atoi(optarg);
254 break;
255
ed10c639
FCE
256 case 'D':
257 s.macros.push_back (string (optarg));
258 break;
259
2b066ec1 260 case 'h':
277c1957
DS
261 usage (s, 0);
262 break;
263
2b066ec1 264 default:
277c1957
DS
265 usage (s, 1);
266 break;
2b066ec1
FCE
267 }
268 }
269
f272aacc
LG
270 if(!s.bulk_mode && !s.merge)
271 {
272 cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
277c1957 273 usage (s, 1);
f272aacc
LG
274 }
275
276 if(!s.output_file.empty() && s.bulk_mode && !s.merge)
277 {
278 cerr << "You can't specify -M, -b and -o options together." <<endl;
277c1957 279 usage (s, 1);
f272aacc
LG
280 }
281
2b066ec1
FCE
282 for (int i = optind; i < argc; i++)
283 {
284 if (! have_script)
285 {
286 script_file = string (argv[i]);
287 have_script = true;
288 }
289 else
f4b28491 290 s.args.push_back (string (argv[i]));
2b066ec1
FCE
291 }
292
293 // need a user file
294 if (! have_script)
277c1957
DS
295 {
296 cerr << "A script must be specified." << endl;
297 usage(s, 1);
298 }
f4b28491
FCE
299
300 int rc = 0;
2b066ec1 301
ce3187ac 302 // override PATH and LC_ALL
f8949662 303 char* path = "PATH=/bin:/sbin:/usr/bin:/usr/sbin";
ce3187ac
FCE
304 char* lc_all = "LC_ALL=C";
305 rc = putenv (path) || putenv (lc_all);
306 if (rc)
307 {
308 const char* e = strerror (errno);
309 cerr << "setenv (\"" << path << "\" + \"" << lc_all << "\"): "
310 << e << endl;
311 }
f8949662 312
ce3187ac 313
2b066ec1
FCE
314 // arguments parsed; get down to business
315
f4b28491
FCE
316 // Create a temporary directory to build within.
317 // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
318 {
ea8ea02c
FCE
319 char* tmpdir_env = getenv("TMPDIR");
320 if (! tmpdir_env)
321 tmpdir_env = "/tmp";
322
323 string stapdir = "/stapXXXXXX";
324 string tmpdirt = tmpdir_env + stapdir;
325 const char* tmpdir = mkdtemp((char *)tmpdirt.c_str());
f4b28491
FCE
326 if (! tmpdir)
327 {
328 const char* e = strerror (errno);
ea8ea02c
FCE
329 cerr << "ERROR: cannot create temporary directory (\"" << tmpdirt << "\"): " << e << endl;
330 exit (1); // die
f4b28491
FCE
331 }
332 else
333 s.tmpdir = tmpdir;
0d49d7bc 334
b0ee93c4 335 if (s.verbose>1)
0d49d7bc 336 clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491 337 }
2b066ec1 338
5ee1c56b
FCE
339 struct tms tms_before;
340 times (& tms_before);
1d738eed
FCE
341 struct timeval tv_before;
342 gettimeofday (&tv_before, NULL);
2b066ec1
FCE
343
344 // PASS 1a: PARSING USER SCRIPT
345 // XXX: pass args vector, so parser (or lexer?) can substitute
346 // $1..$NN with actual arguments
69c68955 347 if (script_file == "-")
177a8ead 348 s.user_file = parser::parse (s, cin, s.guru_mode);
69c68955 349 else if (script_file != "")
177a8ead 350 s.user_file = parser::parse (s, script_file, s.guru_mode);
2b066ec1
FCE
351 else
352 {
353 istringstream ii (cmdline_script);
177a8ead 354 s.user_file = parser::parse (s, ii, s.guru_mode);
2b066ec1
FCE
355 }
356 if (s.user_file == 0)
357 // syntax errors already printed
358 rc ++;
377b8831 359
5519d363 360 // Construct arch / kernel-versioning search path
377b8831 361 vector<string> version_suffixes;
6f9f33e2 362 string kvr = s.kernel_release;
5519d363
KS
363 const string& arch = s.architecture;
364 // add full kernel-version-release (2.6.NN-FOOBAR) + arch
365 version_suffixes.push_back ("/" + kvr + "/" + arch);
377b8831 366 version_suffixes.push_back ("/" + kvr);
5519d363 367 // add kernel version (2.6.NN) + arch
77a5c1f9
JS
368 string::size_type dash_index = kvr.find ('-');
369 if (dash_index > 0 && dash_index != string::npos) {
6f9f33e2
JS
370 kvr.erase(dash_index);
371 version_suffixes.push_back ("/" + kvr + "/" + arch);
372 version_suffixes.push_back ("/" + kvr);
5519d363
KS
373 }
374 // add kernel family (2.6) + arch
6f9f33e2
JS
375 string::size_type dot1_index = kvr.find ('.');
376 string::size_type dot2_index = kvr.rfind ('.');
377 while (dot2_index > dot1_index && dot2_index != string::npos) {
378 kvr.erase(dot2_index);
379 version_suffixes.push_back ("/" + kvr + "/" + arch);
380 version_suffixes.push_back ("/" + kvr);
381 dot2_index = kvr.rfind ('.');
5519d363
KS
382 }
383 // add architecture search path
384 version_suffixes.push_back("/" + arch);
377b8831
FCE
385 // add empty string as last element
386 version_suffixes.push_back ("");
2b066ec1
FCE
387
388 // PASS 1b: PARSING LIBRARY SCRIPTS
f4b28491 389 for (unsigned i=0; i<s.include_path.size(); i++)
2b066ec1 390 {
377b8831
FCE
391 // now iterate upon it
392 for (unsigned k=0; k<version_suffixes.size(); k++)
2b066ec1 393 {
377b8831
FCE
394 glob_t globbuf;
395 string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
396 int r = glob(dir.c_str (), 0, NULL, & globbuf);
397 if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
2b066ec1 398 rc ++;
377b8831
FCE
399 // GLOB_NOMATCH is acceptable
400
b0ee93c4 401 if (s.verbose>1)
377b8831
FCE
402 clog << "Searched '" << dir << "', "
403 << "match count " << globbuf.gl_pathc << endl;
2b066ec1 404
377b8831
FCE
405 for (unsigned j=0; j<globbuf.gl_pathc; j++)
406 {
24cb178f 407 // privilege only for /usr/share/systemtap?
177a8ead 408 stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true);
377b8831
FCE
409 if (f == 0)
410 rc ++;
411 else
24cb178f 412 s.library_files.push_back (f);
377b8831 413 }
d54d4661 414
377b8831
FCE
415 globfree (& globbuf);
416 }
2b066ec1
FCE
417 }
418
f4b28491 419 if (rc == 0 && s.last_pass == 1)
2b066ec1 420 {
f4b28491
FCE
421 cout << "# parse tree dump" << endl;
422 s.user_file->print (cout);
423 cout << endl;
ae56fddd
FCE
424 if (s.verbose)
425 for (unsigned i=0; i<s.library_files.size(); i++)
426 {
427 s.library_files[i]->print (cout);
428 cout << endl;
429 }
2b066ec1
FCE
430 }
431
5ee1c56b
FCE
432 struct tms tms_after;
433 times (& tms_after);
434 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
1d738eed
FCE
435 struct timeval tv_after;
436 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
437
438#define TIMESPRINT \
439 (tms_after.tms_cutime + tms_after.tms_utime \
1d738eed 440 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
5ee1c56b 441 << (tms_after.tms_cstime + tms_after.tms_stime \
1d738eed
FCE
442 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
443 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
444 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
5ee1c56b 445
eaf134e7 446 // syntax errors, if any, are already printed
5ee1c56b
FCE
447 if (s.verbose)
448 {
449 clog << "Pass 1: parsed user script and "
450 << s.library_files.size()
451 << " library script(s) in "
452 << TIMESPRINT
453 << endl;
454 }
0d49d7bc 455
2cfb0e46
FCE
456 if (rc)
457 cerr << "Pass 1: parse failed. "
213bee8f 458 << "Try again with more '-v' (verbose) options."
2cfb0e46
FCE
459 << endl;
460
0d49d7bc 461 if (rc || s.last_pass == 1) goto cleanup;
f4b28491 462
5ee1c56b 463 times (& tms_before);
1d738eed 464 gettimeofday (&tv_before, NULL);
5ee1c56b 465
2b066ec1 466 // PASS 2: ELABORATION
0d49d7bc 467 rc = semantic_pass (s);
f4b28491
FCE
468
469 if (rc == 0 && s.last_pass == 2)
2b066ec1 470 {
553d27a5 471 if (s.globals.size() > 0)
f4b28491 472 cout << "# globals" << endl;
2b066ec1
FCE
473 for (unsigned i=0; i<s.globals.size(); i++)
474 {
475 vardecl* v = s.globals[i];
f4b28491
FCE
476 v->printsig (cout);
477 cout << endl;
2b066ec1
FCE
478 }
479
553d27a5 480 if (s.functions.size() > 0)
f4b28491 481 cout << "# functions" << endl;
2b066ec1
FCE
482 for (unsigned i=0; i<s.functions.size(); i++)
483 {
484 functiondecl* f = s.functions[i];
f4b28491
FCE
485 f->printsig (cout);
486 cout << endl;
553d27a5 487 if (f->locals.size() > 0)
f4b28491 488 cout << " # locals" << endl;
553d27a5
FCE
489 for (unsigned j=0; j<f->locals.size(); j++)
490 {
491 vardecl* v = f->locals[j];
f4b28491
FCE
492 cout << " ";
493 v->printsig (cout);
494 cout << endl;
553d27a5 495 }
cbfbbf69
FCE
496 if (s.verbose)
497 {
498 f->body->print (cout);
499 cout << endl;
500 }
2b066ec1
FCE
501 }
502
553d27a5 503 if (s.probes.size() > 0)
f4b28491 504 cout << "# probes" << endl;
2b066ec1
FCE
505 for (unsigned i=0; i<s.probes.size(); i++)
506 {
507 derived_probe* p = s.probes[i];
f4b28491
FCE
508 p->printsig (cout);
509 cout << endl;
553d27a5 510 if (p->locals.size() > 0)
f4b28491 511 cout << " # locals" << endl;
553d27a5
FCE
512 for (unsigned j=0; j<p->locals.size(); j++)
513 {
514 vardecl* v = p->locals[j];
f4b28491
FCE
515 cout << " ";
516 v->printsig (cout);
517 cout << endl;
553d27a5 518 }
cbfbbf69
FCE
519 if (s.verbose)
520 {
521 p->body->print (cout);
522 cout << endl;
523 }
2b066ec1
FCE
524 }
525 }
526
5ee1c56b 527 times (& tms_after);
1d738eed
FCE
528 gettimeofday (&tv_after, NULL);
529
b0ee93c4 530 if (s.verbose) clog << "Pass 2: analyzed script: "
0d49d7bc
FCE
531 << s.probes.size() << " probe(s), "
532 << s.functions.size() << " function(s), "
5ee1c56b
FCE
533 << s.globals.size() << " global(s) in "
534 << TIMESPRINT
535 << endl;
0d49d7bc 536
377b8831
FCE
537 if (rc)
538 cerr << "Pass 2: analysis failed. "
213bee8f 539 << "Try again with more '-v' (verbose) options."
2cfb0e46 540 << endl;
377b8831 541
0d49d7bc 542 if (rc || s.last_pass == 2) goto cleanup;
f4b28491 543
2b066ec1 544 // PASS 3: TRANSLATION
5ee1c56b
FCE
545
546 times (& tms_before);
1d738eed
FCE
547 gettimeofday (&tv_before, NULL);
548
0d49d7bc
FCE
549 s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
550 rc = translate_pass (s);
f4b28491
FCE
551
552 if (rc == 0 && s.last_pass == 3)
553 {
554 ifstream i (s.translated_source.c_str());
555 cout << i.rdbuf();
556 }
0d49d7bc 557
5ee1c56b 558 times (& tms_after);
1d738eed 559 gettimeofday (&tv_after, NULL);
5ee1c56b 560
0d49d7bc
FCE
561 if (s.verbose) clog << "Pass 3: translated to C into \""
562 << s.translated_source
5ee1c56b
FCE
563 << "\" in "
564 << TIMESPRINT
565 << endl;
0d49d7bc 566
377b8831 567 if (rc)
2cfb0e46 568 cerr << "Pass 3: translation failed. "
213bee8f 569 << "Try again with more '-v' (verbose) options."
2cfb0e46 570 << endl;
377b8831 571
0d49d7bc 572 if (rc || s.last_pass == 3) goto cleanup;
d54d4661 573
f4b28491 574 // PASS 4: COMPILATION
5ee1c56b 575 times (& tms_before);
1d738eed 576 gettimeofday (&tv_before, NULL);
0d49d7bc 577 rc = compile_pass (s);
5ee1c56b 578 times (& tms_after);
1d738eed 579 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
580
581 if (s.verbose) clog << "Pass 4: compiled C into \""
582 << s.module_name << ".ko"
583 << "\" in "
584 << TIMESPRINT
585 << endl;
f4b28491 586
eaf134e7
FCE
587 if (rc)
588 cerr << "Pass 4: compilation failed. "
213bee8f 589 << "Try again with more '-v' (verbose) options."
2cfb0e46 590 << endl;
eaf134e7 591
f8949662 592 // XXX: what to do if rc==0 && last_pass == 4? dump .ko file to stdout?
0d49d7bc 593 if (rc || s.last_pass == 4) goto cleanup;
f4b28491 594
0d49d7bc 595 // PASS 5: RUN
5ee1c56b 596 times (& tms_before);
1d738eed 597 gettimeofday (&tv_before, NULL);
03d569d3
FCE
598 // NB: this message is a judgement call. The other passes don't emit
599 // a "hello, I'm starting" message, but then the others aren't interactive
600 // and don't take an indefinite amount of time.
601 if (s.verbose) clog << "Pass 5: starting run." << endl;
0d49d7bc 602 rc = run_pass (s);
5ee1c56b 603 times (& tms_after);
1d738eed 604 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
605 if (s.verbose) clog << "Pass 5: run completed in "
606 << TIMESPRINT
607 << endl;
f4b28491 608
eaf134e7
FCE
609 if (rc)
610 cerr << "Pass 5: run failed. "
213bee8f 611 << "Try again with more '-v' (verbose) options."
2cfb0e46 612 << endl;
eaf134e7 613
0d49d7bc 614 // if (rc) goto cleanup;
2b066ec1 615
0d49d7bc 616 cleanup:
f4b28491
FCE
617 // Clean up temporary directory. Obviously, be careful with this.
618 if (s.tmpdir == "")
619 ; // do nothing
620 else
621 {
622 if (s.keep_tmpdir)
0d49d7bc 623 clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491
FCE
624 else
625 {
ce3187ac 626 string cleanupcmd = "rm -rf ";
f4b28491 627 cleanupcmd += s.tmpdir;
b0ee93c4 628 if (s.verbose>1) clog << "Running " << cleanupcmd << endl;
d54d4661 629 int status = system (cleanupcmd.c_str());
b0ee93c4 630 if (status != 0 && s.verbose>1)
d54d4661 631 clog << "Cleanup command failed, status: " << status << endl;
f4b28491
FCE
632 }
633 }
2b066ec1 634
54dfabe9 635 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
2b066ec1 636}
This page took 0.119365 seconds and 5 git commands to generate.