Re: getting the path to the executing program
Hal Daume wrote:
is there a function, related to getProgName, which returns the (absolute) path to the current program?
basically, i want to be able to read a file which i know will be in the same directory as the current program, but not necessarily in the same directory that we're running it from.
Actually, if you want to read a file located in the same directory as the executable itself, you don't need the absolute path of the executable. You merely need any path to the executable that is valid with respect to the working directory at the start-up time. Some four years ago I wrote a similar code that seems to work reliably across HP/UX, Solaris, Linux, FreeBSD and various versions of Winxx (from Windows98 onwards). The application has been deployed in more than thousand copies and nobody has complained regarding the path. The application reliably finds the name of a file from the application's own directory no matter how the application was invoked: from its own directory by name, from its own directory as "./appname", from its own directory by the absolute or relative (../dir/appname) name, or from some other directory by the absolute or relative name, or by a symbolic link. The only assumption is that neither forward nor backward slash can appear in a file path. The latter assumption seems to always hold on Winxx, which takes the forward slash as a path delimiter too. On Unixen, the backward slash in file names seems to appear only on hacked systems. So, the failure of the approach in that case should be considered a feature. The algorithm is simple: remove the last path-component from argv[0] and append the local file name to the result (which may be an empty string). A path component is a sequence of characters that does not contain a path delimiter. Note that argv[0] may not end in a path delimiter. The algorithm requires argv[0] as it is given by the OS. Alas, neither GHC nor Hugs seem to give us that. Therefore, I'm inclosing the Scheme code that implements the algorithm. I do not have the guts to post the original code (which was in Perl). If I may suggest, a Haskell implementation may want to give a programmer a way to obtain the unmangled argv0. ; last-delimiter STR -> POS ; where POS is the location of the last path-delimiter in STR ; or #f (define delimiters '(#\\ #\/)) (define (last-delimiter str) (let loop ((i (- (string-length str) 1))) (cond ((negative? i) #f) ((memv (string-ref str i) delimiters) i) (else (loop (- i 1)))))) (define local-file-name "that-is-it") ; Like with-input-from file, but the file ; is assumed to be in the same directory as the executable ; itself (define (with-input-from-local-file local-file-name thunk) (let* ((argv0 (car (command-line))) (last-delim (last-delimiter argv0))) (with-input-from-file (if last-delim (if (< (+ 1 last-delim) (string-length argv0)) (string-append (substring argv0 0 (+ 1 last-delim)) local-file-name) (error 'with-input-from-local-file "path-delim at the end of argv0: " argv0)) local-file-name) thunk))) (display (with-input-from-local-file local-file-name read)) (newline)
Hi,
If I may suggest, a Haskell implementation may want to give a programmer a way to obtain the unmangled argv0.
If I may second that, ... -- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
Hal Daume III <hdaume@ISI.EDU> writes:
If I may suggest, a Haskell implementation may want to give a programmer a way to obtain the unmangled argv0.
If I may second that, ...
You mean like nhc98 and hbc have always done...? Regards, Malcolm
oleg@pobox.com wrote:
is there a function, related to getProgName, which returns the (absolute) path to the current program?
basically, i want to be able to read a file which i know will be in the same directory as the current program, but not necessarily in the same directory that we're running it from.
Actually, if you want to read a file located in the same directory as the executable itself, you don't need the absolute path of the executable. You merely need any path to the executable that is valid with respect to the working directory at the start-up time.
Some four years ago I wrote a similar code that seems to work reliably across HP/UX, Solaris, Linux, FreeBSD and various versions of Winxx (from Windows98 onwards). The application has been deployed in more than thousand copies and nobody has complained regarding the path. The application reliably finds the name of a file from the application's own directory no matter how the application was invoked: from its own directory by name, from its own directory as "./appname", from its own directory by the absolute or relative (../dir/appname) name, or from some other directory by the absolute or relative name, or by a symbolic link.
You omitted the most important case: from an arbitrary directory via a simple filename, looked up via $PATH. For that case, you need to iterate through the components of $PATH until you find one which contains a suitably-named file which has execute permission for the current user. That still doesn't handle the pathological cases, e.g. where the filesystem has been changed such that the original command would no longer refer to the same executable, or where argv[0] doesn't contain the filename used, but it's likely to be close enough for the cases where someone isn't deliberately trying to make it fail. -- Glynn Clements <glynn.clements@virgin.net>
participants (4)
-
Glynn Clements -
Hal Daume III -
Malcolm Wallace -
oleg@pobox.com