
Hi, getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation: getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO () Discussion deadline: 2 weeks -- Johan

On 13 June 2012 07:57, Johan Tibell
Hi,
getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
Discussion deadline: 2 weeks
+1 Conrad.

Hello,
getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
+1 P.S. I would also like to have an API to change the process name for daemon. --Kazu

I don't think this is guaranteed to work. See top answer here [1]
(which cites the standard). Also, note that the man page for exec and
friends notes that the first argument *by convention* is the name of
the executable.
I'm not against exposing a function to return argv[0] (I thought
getProgName did that), but the documentation should make clear that it
is not guaranteed to work.
[1]: http://stackoverflow.com/questions/2050961/is-argv0-name-of-executable-an-ac...
On 13 June 2012 00:57, Johan Tibell
Hi,
getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
Discussion deadline: 2 weeks
-- Johan
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
-- Push the envelope. Watch it bend.

On Tue, Jun 12, 2012 at 5:59 PM, Thomas Schilling
I don't think this is guaranteed to work. See top answer here [1] (which cites the standard). Also, note that the man page for exec and friends notes that the first argument *by convention* is the name of the executable.
That's right. argv[0] could be anything, including "my hair is on fire". In this sense getFullProgName is as incorrect/correct as getProgName. In practice it will be the program name and then getFullProgName can be used to do useful work, other than printing the program base name, unlike getProgName. :) -- Johan

On 06/13/2012 03:21 AM, Johan Tibell wrote:
On Tue, Jun 12, 2012 at 5:59 PM, Thomas Schilling
wrote: I don't think this is guaranteed to work. See top answer here [1] (which cites the standard). Also, note that the man page for exec and friends notes that the first argument *by convention* is the name of the executable.
That's right. argv[0] could be anything, including "my hair is on fire". In this sense getFullProgName is as incorrect/correct as getProgName. In practice it will be the program name and then getFullProgName can be used to do useful work, other than printing the program base name, unlike getProgName. :)
Not saying it's not an improvement over getProgName (definitely is), but if the intent is to provide the most accurate name of the executable which is running, then... You should probably read the /proc/self/exe symlink on Linux. (Of course /proc may not be mounted so you'll need a fallback in any case...) I believe FreeBSD and Solaris have similar methods using /proc. On Win32 it seems that using GetModuleFileName with a NULL first parameter is the way to go: http://msdn.microsoft.com/en-us/library/ms683197%28VS.85%29.aspx Regards,

On Tue, Jun 12, 2012 at 8:08 PM, Bardur Arantsson
Not saying it's not an improvement over getProgName (definitely is), but if the intent is to provide the most accurate name of the executable which is running, then...
You should probably read the /proc/self/exe symlink on Linux. (Of course /proc may not be mounted so you'll need a fallback in any case...)
I believe FreeBSD and Solaris have similar methods using /proc.
On Win32 it seems that using GetModuleFileName with a NULL first parameter is the way to go:
http://msdn.microsoft.com/en-us/library/ms683197%28VS.85%29.aspx
Good ideas. If we do that, do we also want a way to access the raw argv[0]?

On 13/06/2012 05:49, Johan Tibell wrote:
On Tue, Jun 12, 2012 at 8:08 PM, Bardur Arantsson
wrote: Not saying it's not an improvement over getProgName (definitely is), but if the intent is to provide the most accurate name of the executable which is running, then...
You should probably read the /proc/self/exe symlink on Linux. (Of course /proc may not be mounted so you'll need a fallback in any case...)
I believe FreeBSD and Solaris have similar methods using /proc.
On Win32 it seems that using GetModuleFileName with a NULL first parameter is the way to go:
http://msdn.microsoft.com/en-us/library/ms683197%28VS.85%29.aspx
Good ideas. If we do that, do we also want a way to access the raw argv[0]?
I suggest we should have a getExecutablePath :: IO FilePath in System.Environment. We have an implementation for Windows in GHC that we use to find GHC's files relative to ghc.exe. This SO question has some good references for ways to do it on different platforms: http://stackoverflow.com/questions/1023306/finding-current-executables-path-... We should also have something in System.Posix to return the original argv[0], unfortunately we forgot about this when adding System.Posix.ByteString.getArgs which returns argv[1..]. Maybe System.Posix.ByteString.getProgName :: IO ByteString Cheers, Simon

On Wed, Jun 13, 2012 at 2:05 AM, Simon Marlow
I suggest we should have a
getExecutablePath :: IO FilePath
in System.Environment. We have an implementation for Windows in GHC that we use to find GHC's files relative to ghc.exe. This SO question has some good references for ways to do it on different platforms:
http://stackoverflow.com/questions/1023306/finding-current-executables-path-...
I'm up for doing this instead of adding getFullProgName.
We should also have something in System.Posix to return the original argv[0], unfortunately we forgot about this when adding System.Posix.ByteString.getArgs which returns argv[1..].
How long ago was this added. Is there a chance we can make a breaking change without affecting lots of programs? -- Johan

Isn't this about 24 years overdue? Can we do it now. (Only kidding, but seriously...) Chris -----Original Message----- From: libraries-bounces@haskell.org [mailto:libraries-bounces@haskell.org] On Behalf Of Johan Tibell Sent: 13 June 2012 00:57 To: Haskell Libraries Subject: Proposal: Add getFullProgName Hi, getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation: getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO () Discussion deadline: 2 weeks -- Johan _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Hi Johan, On Tue, Jun 12, 2012 at 04:57:00PM -0700, Johan Tibell wrote:
getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
Are those 3 peeks all guaranteed to not be of NULL pointers on all platforms and in all situations? If not, wouldn't it be better to check for NULL and throw an exception? Thanks Ian

On Tue, Jun 12, 2012 at 6:10 PM, Ian Lynagh
Are those 3 peeks all guaranteed to not be of NULL pointers on all platforms and in all situations?
If not, wouldn't it be better to check for NULL and throw an exception?
Will do that. I plan to look at what getProgName does to make sure we do the same, module mangling the string. -- Johan

getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
Discussion deadline: 2 weeks
This has bothered me for some time, so I really think we should do something about it. But I also think that argv[0] is only sane for compiled programs. If you run it with `runhaskell` or from `ghci` it will give you the path to ghc, which is not what I'd expect (from a users point of view). In analogous to getProgName I'd suggest to: * Return the full path to the script for `runhaskell` * Return "<interactive>" when run from GHCi Or we could make it explicit: getFullProgName :: IO ExecutablePath data ExecutablePath = Binary FilePath | Script FilePath | Interactive For reference, there are several packages on Hackage that try to solve this in some way [1][2][3]. Cheers, Simon [1] http://hackage.haskell.org/package/FindBin [2] http://hackage.haskell.org/package/executable-path [3] http://hackage.haskell.org/package/system-argv0

On Wed, Jun 13, 2012 at 9:38 AM, Simon Hengel
data ExecutablePath = Binary FilePath | Script FilePath | Interactive
Do we want to force implementations to be able to distinguish binary from script? Does that distinction even always make sense? Certainly it's easy to imagine some implementations for which "Interactive" would be useless. I think it's hard to come up with a decent getFullProgName that doesn't make a lot of assumptions about what sort of environment we are in. getProgName is at least simpler in that regard.

+1
On Jun 12, 2012, at 7:57 PM, Johan Tibell
Hi,
getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
Discussion deadline: 2 weeks
-- Johan
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 6/12/12 7:57 PM, Johan Tibell wrote:
Hi,
getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv>>= peek>>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
Discussion deadline: 2 weeks
FWIW, cf: http://hackage.haskell.org/package/system-argv0 -- Live well, ~wren

Johan Tibell wrote:
getProgName is only useful in case you want to print the program name to the screen. You cannot actually use it to do anything interesting programmatically (like execv:ing the program.) I suggest we add getFullProgName which does the sensible thing of returning argv[0]. Here's an implementation:
getFullProgName :: IO String getFullProgName = alloca $ \ p_argc -> alloca $ \ p_argv -> do getFullProgArgv p_argc p_argv peek p_argv >>= peek >>= peekCString
foreign import ccall unsafe "getFullProgArgv" getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
While getFullProgramName is a very useful function, I don't think that the proposed implementation is any good. -1 The trouble is that getFullProgramName needs to be portable across different platforms. If it works on UNIX platforms but not on any other platform (Windows? Android?), we will just end up with Haskell code that works correctly only on UNIX, and subtly breaks everywhere else. I don't think that this is a good idea. Also, the package http://hackage.haskell.org/package/executable-path provides a portable way to get the path of an executable. If more standardization is required, I would argue that we should include it in the Haskell Platform or integrate the source code into base. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

I've modified the proposal (in an earlier email) to be to add getExecutablePath. We'll implement it using the methods Simon linked to, which I believe are the same as used in executable-path. -- Johan

Johan Tibell wrote:
I've modified the proposal (in an earlier email) to be to add getExecutablePath. We'll implement it using the methods Simon linked to, which I believe are the same as used in executable-path.
Ah, ok. That works for me. Reading Simon Hengel's email, I think that distinguishing between different invocation methods (program, script, interactive) via a data type data ExecutablePath = Binary FilePath | Script FilePath | Interactive is an excellent idea! This allows us to use the getExecutablePath both in a compiled program and for testing in GHCi. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

On Sun, Jun 17, 2012 at 2:20 AM, Heinrich Apfelmus
Johan Tibell wrote:
I've modified the proposal (in an earlier email) to be to add getExecutablePath. We'll implement it using the methods Simon linked to, which I believe are the same as used in executable-path.
Ah, ok. That works for me.
Reading Simon Hengel's email, I think that distinguishing between different invocation methods (program, script, interactive) via a data type
data ExecutablePath = Binary FilePath | Script FilePath | Interactive
is an excellent idea! This allows us to use the getExecutablePath both in a compiled program and for testing in GHCi.
I'm a bit undecided whether this distinction is useful. If the user is really looking for the executable path there's not much to do except call error if the return value is Script or Interactive. In addition, I don't know how to implement this function correctly. For example, if you alias ghc to another name the heuristic in the executable-path package fails: -- | An experimental hack which tries to figure out if the program -- was run with @runghc@ or @runhaskell@ or @ghci@, and then tries to find -- out the directory of the /source/ (or object file). -- -- GHC only. getScriptPath :: IO ScriptPath getScriptPath = do fargs <- getFullArgs exec <- getExecutablePath let (pt,fn) = splitFileName exec case fargs of [] -> return (Executable exec) _ -> case map toLower fn of #ifdef mingw32_HOST_OS "ghc.exe" -> do #else "ghc" -> do #endif case find f1 fargs of Just s -> do path <- canonicalizePath $ init (drop n1 s) return $ RunGHC path Nothing -> case findIndex f2 fargs of Just i -> return Interactive Nothing -> return (Executable exec) _ -> return (Executable exec) where f1 xs = take n1 xs == s1 s1 = ":set prog \"" n1 = length s1 f2 xs = xs == "--interactive"

Johan Tibell wrote:
On Sun, Jun 17, 2012 at 2:20 AM, Heinrich Apfelmus
Reading Simon Hengel's email, I think that distinguishing between different invocation methods (program, script, interactive) via a data type
data ExecutablePath = Binary FilePath | Script FilePath | Interactive
is an excellent idea! This allows us to use the getExecutablePath both in a compiled program and for testing in GHCi.
I'm a bit undecided whether this distinction is useful. If the user is really looking for the executable path there's not much to do except call error if the return value is Script or Interactive.
The main use I have in mind is that it makes it easier to develop and test your program in GHCi. By distinguishing cases, you can invoke the program as either ./myprogram or runhaskell myprogram.hs and still get a good path.
In addition, I don't know how to implement this function correctly. For example, if you alias ghc to another name the heuristic in the executable-path package fails:
Good point. For the use case mentioned above, any quick and dirty heuristic that works most of the time would be sufficient, though. Ideally, Haskell interpreters would set an environment variable when they interpret a source file. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

Hi! On Tue, Jun 19, 2012 at 7:53 AM, Heinrich Apfelmus < apfelmus@quantentunnel.de> wrote:
In addition, I don't know how to implement this function correctly.
For example, if you alias ghc to another name the heuristic in the executable-path package fails:
Good point. For the use case mentioned above, any quick and dirty heuristic that works most of the time would be sufficient, though.
Ideally, Haskell interpreters would set an environment variable when they interpret a source file.
Since * we can't implement this reliably, * the distinction into these three groups doesn't necessarily work for all compilers, and * the distinction (I assume) isn't useful in most use cases I think people who want to use this heuristic are better served by the existing executable-path package. What do you think? -- Johan

On Tue, Jun 19, 2012 at 8:54 AM, Johan Tibell
Hi!
On Tue, Jun 19, 2012 at 7:53 AM, Heinrich Apfelmus < apfelmus@quantentunnel.de> wrote:
In addition, I don't know how to implement this function correctly.
For example, if you alias ghc to another name the heuristic in the executable-path package fails:
Good point. For the use case mentioned above, any quick and dirty heuristic that works most of the time would be sufficient, though.
Ideally, Haskell interpreters would set an environment variable when they interpret a source file.
Since
* we can't implement this reliably, * the distinction into these three groups doesn't necessarily work for all compilers, and * the distinction (I assume) isn't useful in most use cases
Another problem with the executable-path like distinction is that it's no longer possible to find out which executable (i.e. ghc) is running the script. At a minimum the Script and Interactive constructors would have to expose that. getExecutablePath :: IO FilePath has a clear meaning: return the path to the executable that's currently executing. If we want a function that provides the script/interactive/executable guessing, we should provide both functions. The guessing one should have this warning: -- N.B. This function might return Executable in the case of Script/Interactive and vice versa. -- Johan

Johan Tibell wrote:
On Tue, Jun 19, 2012 at 8:54 AM, Johan Tibell
wrote: Since
* we can't implement this reliably, * the distinction into these three groups doesn't necessarily work for all compilers, and * the distinction (I assume) isn't useful in most use cases
Another problem with the executable-path like distinction is that it's no longer possible to find out which executable (i.e. ghc) is running the script. At a minimum the Script and Interactive constructors would have to expose that.
getExecutablePath :: IO FilePath
has a clear meaning: return the path to the executable that's currently executing.
That's true, I think the well-defined semantics are a clear point in favor of the simple getExecutablePath function. The only trouble I have is that these semantics don't seem to be useful. For what purpose would you like to know the executable path? The only use case that I have encountered is to find data files relative to the program, but in this case, I need it to work equally well in GHCi, runghc and compiled. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

Hi Heinrich,
On Wed, Jun 20, 2012 at 2:02 AM, Heinrich Apfelmus
The only trouble I have is that these semantics don't seem to be useful. For what purpose would you like to know the executable path? The only use case that I have encountered is to find data files relative to the program, but in this case, I need it to work equally well in GHCi, runghc and compiled.
The most common use case I can think of is having the binary invoke itself in some way e.g. using execv. The particular use case I have in mind is having the binary copy itself elsewhere (i.e. to another machine) and then execute itself again. -- Johan

2012/6/20 Johan Tibell
Hi Heinrich,
On Wed, Jun 20, 2012 at 2:02 AM, Heinrich Apfelmus
wrote: The only trouble I have is that these semantics don't seem to be useful. For what purpose would you like to know the executable path? The only use case that I have encountered is to find data files relative to the program, but in this case, I need it to work equally well in GHCi, runghc and compiled.
The most common use case I can think of is having the binary invoke itself in some way e.g. using execv. The particular use case I have in mind is having the binary copy itself elsewhere (i.e. to another machine) and then execute itself again.
I know this a special case and slightly off-topic. However, I'm not sure, if this use-case provides a good justification for 'getExecutablePath'. Couldn't you just pass an explicit argument with the path to the file to copy when executing this binary? Your shortcut via 'getExecutablePath' somehow reminds me of an arbitrary IO action deep-down in some module trying to call 'main' again. This requires quite some impurity to achieve and entails a slew of composability issues. The pure construction of explicitly passing all arguments was always much simpler in my code. best regards, Simon

On Thu, Jun 21, 2012 at 1:51 AM, Simon Meier
I know this a special case and slightly off-topic. However, I'm not sure, if this use-case provides a good justification for 'getExecutablePath'. Couldn't you just pass an explicit argument with the path to the file to copy when executing this binary?
It's possible, but I think we can do better. First, it's kinda silly to require the user to type: /some/dir/my-binary /some/dir/my-binary Second, in the presence of symlinks it can be tricky for the user to figure out what the right path is and, since the OS has already resolved that issue when launching the executable, it makes sense to use the info the OS has (to avoid having the OS and the user disagree over where the executable lives if nothing else.) Third, the fact that I copy the executable somewhere is something I like to keep behind the scenes and not include in the UI.
Your shortcut via 'getExecutablePath' somehow reminds me of an arbitrary IO action deep-down in some module trying to call 'main' again. This requires quite some impurity to achieve and entails a slew of composability issues. The pure construction of explicitly passing all arguments was always much simpler in my code.
I'm not using any unsafe I/O anywhere. I want to replace (the non-working): main = do file <- getProgName ... with main = do file <- getExecutablePath ... All my actions on file (i.e. copying it, executing it) lives in IO. -- Johan

Johan Tibell wrote:
Hi Heinrich,
On Wed, Jun 20, 2012 at 2:02 AM, Heinrich Apfelmus
wrote: The only trouble I have is that these semantics don't seem to be useful. For what purpose would you like to know the executable path? The only use case that I have encountered is to find data files relative to the program, but in this case, I need it to work equally well in GHCi, runghc and compiled.
The most common use case I can think of is having the binary invoke itself in some way e.g. using execv. The particular use case I have in mind is having the binary copy itself elsewhere (i.e. to another machine) and then execute itself again.
Ah, I see. This use case does not strike me as very common, but I don't think that this is a criterion against inclusion. It may be a good idea to mention the use case in the Haddock documentation, and to point out that running the function in an interpreter context will return the path of the interpreter, just to make it clear what the function can and cannot do. In any case, I'm happy with the proposal now ( getExecutablePath returning precisely the path of the executable). Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

The discussion period is now over. I believe there are no remaining objections to add getExecutablePath which returns the FilePath of the current remaining executable. For those that also want a function that tries to guess whether a script is running, I suggest you open a separate proposal. -- Johan

On Mon, Jun 25, 2012 at 6:04 PM, Johan Tibell
The discussion period is now over.
I believe there are no remaining objections to add getExecutablePath which returns the FilePath of the current remaining executable. For those that also want a function that tries to guess whether a script is running, I suggest you open a separate proposal.
I've created a first implementation [1] for Mac OS X, Linux, and Windows, with a fallback implementation that uses argv[0]. I will need someone to volunteer to test/finish the Windows one, as I don't have access to a Windows machine (perhaps GHC HQ can do this.) 1. https://github.com/tibbe/packages-base/commit/7a3b969c52da9e94c17553d34ec2df... -- Johan

Hello,
On Tue, Jun 19, 2012 at 6:19 PM, Johan Tibell
Another problem with the executable-path like distinction is that it's no longer possible to find out which executable (i.e. ghc) is running the script. At a minimum the Script and Interactive constructors would have to expose that.
getExecutablePath :: IO FilePath
has a clear meaning: return the path to the executable that's currently executing.
Except it does not. First, as the author of the executable-path library, it seems to me that the GHC docs are indeed correct saying that this is impossible to implement on some systems. My (conjectural) example for such systems are older BSD systems (FreeBSD before v6.0 iirc, NetBSD, OpenBSD). And these are even pretty standard Unix systems! Another serious issue is that the notion itself does not seems to be well-defined. For example think about symlinks (soft, hard?). Probably there exist other more strange Unix features I'm not aware of, which are complicating the matter further. Symlinks also exist on Windows by the way, though not advertised much. So, while of course I agree that there is a need for such a function (hence the 3 independent libraries on Hackage trying to provide it), unfortunately the situation is rather muddy.
If we want a function that provides the script/interactive/executable guessing, we should provide both functions. The guessing one should have this warning:
-- N.B. This function might return Executable in the case of Script/Interactive and vice versa.
I agree, clearly the proper solution is to provide both functions. That's also what executable-path does, with big warnings and all. Though I think that the runtime itself can (or could) reliably determine whether it is a script or interactive session, bytecode or compiled, so there is no need to guessing; and since the meaning of this function is implementation-dependent anyway, there is no harm making it GHC-specific. It is also not unprecedented to have GHC-specific functionality in base. Balazs

On Thu, Jun 21, 2012 at 12:10 PM, Balazs Komuves
First, as the author of the executable-path library, it seems to me that the GHC docs are indeed correct saying that this is impossible to implement on some systems. My (conjectural) example for such systems are older BSD systems (FreeBSD before v6.0 iirc, NetBSD, OpenBSD). And these are even pretty standard Unix systems!
But not supported by GHC HQ: http://hackage.haskell.org/trac/ghc/wiki/Platforms This post suggests that we can implement it reliably on all major OS:es: http://stackoverflow.com/a/1024937/298847 The rest can return argv[0]. It's a big improvement over the current state of affairs (i.e. getProgName.)
Another serious issue is that the notion itself does not seems to be well-defined. For example think about symlinks (soft, hard?). Probably there exist other more strange Unix features I'm not aware of, which are complicating the matter further. Symlinks also exist on Windows by the way, though not advertised much.
getExecutablePath would return the actual executable (as found by the OS), bot symlinks. The OS has to resolve symlinks to run the executable, hence it knows where the executable is. -- Johan

@Johan: sorry for the duplicate
* we can't implement this reliably,
If I understand correctly the current System.Environment.getProgName can make this distinction somehow. But from a quick peek at the code, I can't really tell how it's done.
* the distinction into these three groups doesn't necessarily work for all compilers, and
If a compiler does not support script/interactive, it could always return Binary, right?
* the distinction (I assume) isn't useful in most use cases
At this point I would find it useful to define use cases. When I was looking for that functionality, I wanted to find files relative to a script. For binaries I use Cabal's support for data files, but this only works for `cabal install`ed packages.
I think people who want to use this heuristic are better served by the existing executable-path package. What do you think?
I still think that a well-tested, reliable way to do that would be awesome. I'm not sure how hard it is to get it right, though. If we do not support interactive/script, then I think we should at least use a Maybe instead of `error`. Cheers, Simon

On Tue, Jun 19, 2012 at 9:30 AM, Simon Hengel
* we can't implement this reliably,
If I understand correctly the current System.Environment.getProgName can make this distinction somehow. But from a quick peek at the code, I can't really tell how it's done.
It doesn't. It returns whatever string follows the last / in argv[0]. argv[0] can in theory be anything, including "my hair is on fire." :) See the earlier posts in this thread. I don't think it's possible to implement this correctly, except if we change how GHC runs scripts (i.e. by setting an environment variable, but if you do that you might as well just check for the environment variable if you want to know if you're running as a script.)
* the distinction into these three groups doesn't necessarily work for all
compilers, and
If a compiler does not support script/interactive, it could always return Binary, right?
It might also have some 4th, non-compatible option. Even if it only haves a subset, it forces the programmer to write a pattern match that doesn't make sense (as some of the options can never happen.) getExecutablePath :: IO FilePath doesn't have this problem, as it's always defined.
* the distinction (I assume) isn't useful in most use cases
At this point I would find it useful to define use cases. When I was looking for that functionality, I wanted to find files relative to a script. For binaries I use Cabal's support for data files, but this only works for `cabal install`ed packages.
I guess my point is that we cannot implement what you want correctly. We can implement a heuristic that kind-of works most of the time. That's a useful thing to have, but if so as a function built upon a more well-defined getExecutablePath.
I think people who want to use this heuristic are better served by the
existing executable-path package. What do you think?
I still think that a well-tested, reliable way to do that would be awesome. I'm not sure how hard it is to get it right, though.
If we do not support interactive/script, then I think we should at least use a Maybe instead of `error`.
getExecutablePath :: IO FilePath is always defined. It returns the path to the currently running executable, which is e.g. /bin/ghc in case of a script. -- Johan
participants (16)
-
Balazs Komuves
-
Bardur Arantsson
-
Ben Millwood
-
Chris Dornan
-
Conrad Parker
-
Edward Kmett
-
Heinrich Apfelmus
-
Herbert Valerio Riedel
-
Ian Lynagh
-
Johan Tibell
-
Kazu Yamamoto
-
Simon Hengel
-
Simon Marlow
-
Simon Meier
-
Thomas Schilling
-
wren ng thornton