August 07, 2013 Re: Finding the path to a executable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tommi | On Wed, 07 Aug 2013 09:13:03 +0200
"Tommi" <tommitissari@hotmail.com> wrote:
> On Wednesday, 7 August 2013 at 05:31:24 UTC, Alan wrote:
> > Hello! This may seem like a simple question, maybe an embarassing question but how would I fetch the absolute path to the directory where my executable is located? My wording is known to be confusing so I will give an example:
> >
> > cd ~/projects/program
> > dmd Program.d -ofProgram
> >
> > That executable would be located in /home/alan/projects/program for example. SO my question is how would I fetch the absolute path to that directory?
> >
> > Thanks for any help!
>
> This should work on at least couple of systems, but I haven't tested this on other than Mac. Also, it's not completely robust, because paths could be longer than 4096 chars.
>
> version(Windows) {
> import std.c.windows.windows;
> }
> else version(OSX) {
> private extern(C) int _NSGetExecutablePath(char* buf, uint*
> bufsize);
> }
> else version(linux) {
> import std.c.linux.linux;
> }
> else {
> static assert(0);
> }
> import std.conv;
>
> // Returns the full path to the currently running executable
> string executablePath()
> {
> static string cachedExecutablePath;
>
> if (!cachedExecutablePath) {
> char[4096] buf;
> uint filePathLength;
>
> version(Windows) {
> filePathLength = GetModuleFileNameA(null, buf.ptr,
> buf.length - 1);
> assert(filePathLength != 0);
> }
> else version(OSX) {
> filePathLength = cast(uint) (buf.length - 1);
> int res = _NSGetExecutablePath(buf.ptr,
> &filePathLength);
> assert(res == 0);
> }
> else version(linux) {
> filePathLength = readlink(toStringz(selfExeLink),
> buf.ptr, buf.length - 1);
> }
> else {
> static assert(0);
> }
> cachedExecutablePath = to!string(buf[0 ..
> filePathLength]);
> }
> return cachedExecutablePath;
> }
>
> // Returns the file name of the currently running executable
> string executableName()
> {
> return executablePath().baseName();
> }
>
> // Returns the path to the directory of the currently running
> executable
> string executableDirPath()
> {
> return executablePath().dirName();
> }
Yes, this is the way to do it. Never use args[0]: it's useless as it
doesn't follow symlinks (might not even follow aliases, though I'm
not certain), and strictly-speaking can't even be guaranteed to be
correct at all anyway. If it were up to me, args[0] would be eliminated
outright.
|
August 10, 2013 Re: Finding the path to a executable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Wed, Aug 07, 2013 at 12:55:10PM -0400, Nick Sabalausky wrote: > On Wed, 07 Aug 2013 09:13:03 +0200 > "Tommi" <tommitissari@hotmail.com> wrote: > > > On Wednesday, 7 August 2013 at 05:31:24 UTC, Alan wrote: > > > Hello! This may seem like a simple question, maybe an embarassing question but how would I fetch the absolute path to the directory where my executable is located? My wording is known to be confusing so I will give an example: > > > > > > cd ~/projects/program > > > dmd Program.d -ofProgram > > > > > > That executable would be located in /home/alan/projects/program for example. SO my question is how would I fetch the absolute path to that directory? > > > > > > Thanks for any help! > > > > This should work on at least couple of systems, but I haven't tested this on other than Mac. Also, it's not completely robust, because paths could be longer than 4096 chars. > > > > version(Windows) { > > import std.c.windows.windows; > > } > > else version(OSX) { > > private extern(C) int _NSGetExecutablePath(char* buf, uint* > > bufsize); > > } > > else version(linux) { > > import std.c.linux.linux; > > } > > else { > > static assert(0); > > } > > import std.conv; > > > > // Returns the full path to the currently running executable > > string executablePath() > > { > > static string cachedExecutablePath; > > > > if (!cachedExecutablePath) { > > char[4096] buf; > > uint filePathLength; > > > > version(Windows) { > > filePathLength = GetModuleFileNameA(null, buf.ptr, > > buf.length - 1); > > assert(filePathLength != 0); > > } > > else version(OSX) { > > filePathLength = cast(uint) (buf.length - 1); > > int res = _NSGetExecutablePath(buf.ptr, > > &filePathLength); > > assert(res == 0); > > } > > else version(linux) { > > filePathLength = readlink(toStringz(selfExeLink), > > buf.ptr, buf.length - 1); > > } > > else { > > static assert(0); > > } > > cachedExecutablePath = to!string(buf[0 .. > > filePathLength]); > > } > > return cachedExecutablePath; > > } > > > > // Returns the file name of the currently running executable > > string executableName() > > { > > return executablePath().baseName(); > > } > > > > // Returns the path to the directory of the currently running > > executable > > string executableDirPath() > > { > > return executablePath().dirName(); > > } > > Yes, this is the way to do it. Never use args[0]: it's useless as it doesn't follow symlinks (might not even follow aliases, though I'm not certain), and strictly-speaking can't even be guaranteed to be correct at all anyway. +1. If you invoke your program from the shell, it will generally be correct (though unhelpful if the program was found through $PATH, because the shell only passes the bare program name in argv[0], not the full path, leaving you having to search through $PATH all over again -- and even then, there's no guarantee the shell wasn't configured NOT to pass $PATH along: some security models recommend not doing so). But if your program was invoked from another program, there's no guarantee at all what args[0] contains. For all you know, it could be "/path/to/rootkit/maliciousProgram.exe". > If it were up to me, args[0] would be eliminated outright. Naw, there are some valid use cases for it. Take a look at busybox, for example. :) T -- Не дорог подарок, дорога любовь. |
August 11, 2013 Re: Finding the path to a executable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Wed, 7 Aug 2013 10:06:19 -0700
"H. S. Teoh" <hsteoh@quickfur.ath.cx> wrote:
> On Wed, Aug 07, 2013 at 12:55:10PM -0400, Nick Sabalausky wrote:
>
> > If it were up to me, args[0] would be eliminated outright.
>
> Naw, there are some valid use cases for it. Take a look at busybox, for example. :)
>
Hmm, interesting tool. And you're right, I can't think of a better way than args[0] to do what it does.
In any case, Phobos needs to have this "get current executable's path" function if it doesn't already.
|
August 11, 2013 Re: Finding the path to a executable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Sun, 11 Aug 2013 00:45:43 -0400 Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote: > On Wed, 7 Aug 2013 10:06:19 -0700 > "H. S. Teoh" <hsteoh@quickfur.ath.cx> wrote: > > > On Wed, Aug 07, 2013 at 12:55:10PM -0400, Nick Sabalausky wrote: > > > > > If it were up to me, args[0] would be eliminated outright. > > > > Naw, there are some valid use cases for it. Take a look at busybox, for example. :) > > > > Hmm, interesting tool. And you're right, I can't think of a better way than args[0] to do what it does. > > In any case, Phobos needs to have this "get current executable's path" function if it doesn't already. > Pull request: https://github.com/D-Programming-Language/phobos/pull/1463 It's updated from an older version that I had in here: https://bitbucket.org/Abscissa/semitwistdtools/src/c7f89f7cd2c086591b544d5bffc536827ae6f763/src/semitwist/util/io.d?at=master#cl-190 |
Copyright © 1999-2021 by the D Language Foundation