diff --git a/src/node.cc b/src/node.cc index 8f1589ee64..a874c55bba 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1732,6 +1732,16 @@ static void Load(int argc, char *argv[]) { process->Set(String::NewSymbol("pid"), Integer::New(getpid())); + size_t size = 2*PATH_MAX; + char execPath[size]; + if (OS::GetExecutablePath(execPath, &size) != 0) { + // as a last ditch effort, fallback on argv[0] ? + process->Set(String::NewSymbol("execPath"), String::New(argv[0])); + } else { + process->Set(String::NewSymbol("execPath"), String::New(execPath)); + } + + // define various internal methods NODE_SET_METHOD(process, "loop", Loop); NODE_SET_METHOD(process, "unloop", Unloop); diff --git a/src/platform.h b/src/platform.h index 0b9b9be4ad..45f4754726 100644 --- a/src/platform.h +++ b/src/platform.h @@ -6,6 +6,7 @@ namespace node { class OS { public: static int GetMemory(size_t *rss, size_t *vsize); + static int GetExecutablePath(char* buffer, size_t* size); }; diff --git a/src/platform_darwin.cc b/src/platform_darwin.cc index a1bcc107c4..cf0ac711de 100644 --- a/src/platform_darwin.cc +++ b/src/platform_darwin.cc @@ -3,6 +3,7 @@ #include #include +#include /* _NSGetExecutablePath */ namespace node { @@ -26,4 +27,16 @@ int OS::GetMemory(size_t *rss, size_t *vsize) { } +int OS::GetExecutablePath(char* buffer, size_t* size) { + uint32_t usize = *size; + int result = _NSGetExecutablePath(buffer, &usize); + if (result) return result; + char *path = realpath(buffer, NULL); + if (path == NULL) return -1; + strncpy(buffer, path, *size); + free(path); + *size = strlen(buffer); + return 0; +} + } // namespace node diff --git a/src/platform_freebsd.cc b/src/platform_freebsd.cc index 514b796a8f..a0d25dd206 100644 --- a/src/platform_freebsd.cc +++ b/src/platform_freebsd.cc @@ -41,5 +41,17 @@ error: } +int OS::GetExecutablePath(char* buffer, size_t* size) { + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + + if (sysctl(mib, 4, buffer, size, NULL, 0) == -1) { + return -1; + } + return 0; +} } // namespace node diff --git a/src/platform_linux.cc b/src/platform_linux.cc index 13d8c04ac1..95a18b0e0a 100644 --- a/src/platform_linux.cc +++ b/src/platform_linux.cc @@ -89,4 +89,11 @@ error: } +int OS::GetExecutablePath(char* buffer, size_t* size) { + *size = readlink("/proc/self/exe", buffer, *size - 1); + if (*size <= 0) return -1; + buffer[*size] = '\0'; + return 0; +} + } // namespace node diff --git a/src/platform_none.cc b/src/platform_none.cc index 8494c45a95..56a36e1dd5 100644 --- a/src/platform_none.cc +++ b/src/platform_none.cc @@ -12,5 +12,9 @@ int OS::GetMemory(size_t *rss, size_t *vsize) { return 0; } +int OS::GetExecutablePath(char *buffer, size_t* size) { + *size = 0; + return 0; +} } // namespace node diff --git a/src/platform_sunos.cc b/src/platform_sunos.cc index d370dea6e8..34c47fcedd 100644 --- a/src/platform_sunos.cc +++ b/src/platform_sunos.cc @@ -3,6 +3,9 @@ #include /* getpagesize() */ +#include /* getexecname() */ +#include /* strncpy() */ + #if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) #define PROCFS_FILE_OFFSET_BITS_HACK 1 @@ -48,5 +51,24 @@ int OS::GetMemory(size_t *rss, size_t *vsize) { } +int OS::GetExecutablePath(char* buffer, size_t* size) { + const char *execname = getexecname(); + if (!execname) return -1; + if (execname[0] == '/') { + char *result = strncpy(buffer, execname, *size); + *size = strlen(result); + } else { + char *result = getcwd(buffer, *size); + if (!result) return -1; + result = strncat(buffer, "/", *size); + if (!result) return -1; + result = strncat(buffer, execname, *size); + if (!result) return -1; + *size = strlen(result); + } + return 0; +} + + } // namespace node diff --git a/test/simple/test-executable-path.js b/test/simple/test-executable-path.js new file mode 100644 index 0000000000..7b59d4f363 --- /dev/null +++ b/test/simple/test-executable-path.js @@ -0,0 +1,19 @@ +require("../common"); + +path = require("path"); + +isDebug = (process.version.indexOf('debug') >= 0); + +nodePath = path.join(__dirname, + "..", + "..", + "build", + isDebug ? 'debug' : 'default', + isDebug ? 'node_g' : 'node'); +nodePath = path.normalize(nodePath); + +puts('nodePath: ' + nodePath); +puts('process.execPath: ' + process.execPath); + + +assert.equal(nodePath, process.execPath);