1 extern "C" {
2 #include <stdlib.h>
3 #include <string.h>
4 }
5 #include <libcurv/exception.h>
6 #include <libcurv/progdir.h>
7 namespace fs = boost::filesystem;
8 
9 namespace curv {
10 
11 /*
12  * Compute the absolute pathname of the directory
13  * containing the program executable.
14  * The storage for the result string is dynamically allocated.
15  * argv0 is argv[0] of the argv passed to main().
16  */
17 fs::path
progdir(const char * argv0)18 progdir(const char *argv0)
19 {
20     fs::path cmd(argv0);
21 #ifdef _WIN32
22     if (!cmd.has_extension()) cmd += ".exe";
23 #endif
24 
25     if (cmd.has_parent_path()) {
26         return fs::canonical(cmd).parent_path();
27     }
28 
29     const char* PATH = getenv("PATH");
30     if (PATH == NULL) {
31         throw curv::Exception_Base(curv::stringify(
32             "Can't determine directory of program ", argv0,
33             ": PATH not defined"));
34     }
35 
36 
37     const char* p = PATH;
38     const char* pend = PATH + strlen(PATH);
39 #ifdef _WIN32
40     const char delim = ';';
41 #else
42     const char delim = ':';
43 #endif
44     while (p < pend) {
45         const char* q = strchr(p, delim);
46         if (q == nullptr)
47             q = pend;
48         fs::path file(p, q);
49         file /= cmd;
50         if (fs::exists(fs::status(file))) {
51             return fs::canonical(file).parent_path();
52         }
53         p = (q < pend ? q + 1 : pend);
54     }
55 
56     throw curv::Exception_Base(curv::stringify(
57         "Can't determine directory of program ", argv0,
58         ": can't find ", argv0, " in $PATH"));
59 }
60 
61 }
62