The simple question is: how to find out the location of an executable file in a Cocoa application.
Remember that, in many Unix-like OS people use PATH environment to assign the preferred location for their executables, especially when they have several versions of same application in their system. As a good practice, our Cocoa application should find the PREFERRED location of the executable file it needs.
For example, there was a SVN 1.4 in Leopard default configuration at /usr/bin, and you installed a much newer version, say SVN 1.5.3 via MacPorts at /opt/local/bin. And you set your PATH using /etc/path.d or .bash_profile or .zshrc like that:
export PATH=/opt/local/bin:$PATH
So you can use the new version of svn instead of the old one from the system. It works well in any terminal environment. But not in Cocoa applications. Cocoa application, as far as I know, only has a default PATH environment like this:
export PATH="/usr/bin:/bin:/usr/sbin:/sbin"
By default it will not using the configuration in /etc/path.d, .bash_profile, .profile, .zshrc, etc.
So how exactly can we do?
p.s. We have a semi-solution here, but it cannot fully satisfied the objective for this question.
The tricky part of trying to do this is the fact that the user could have their shell set to anything: sh, bash, csh, tcsh, and so on, and each shell sets up its terminal environment differently. I'm not sure if I'd go to the trouble for this myself, but if you really want to, here's the route I would take.
The first step is to figure out the user's shell. On OS X, this information is stored in Directory Services, which can be accesed either through the APIs in DirectoryService.framework or by using the dscl
command line tool. The DirectoryService API is a royal pain in the ass, so I would probably go the CLI route. In Cocoa, you can use NSTask to execute the tool with arguments to get the user's shell (I'll leave the details of this for elsewhere). The command would look something like:
dscl -plist localhost -read /Local/Default/Users/username UserShell
This will return XML text that you can interpret as a plist and transform into an NSDictionary, or you can omit the -plist
option and parse the textual output yourself.
Once you know the path to the user's shell, the next step would be to execute that shell and tell it to run the env
command to print out the user's environment. It looks like most shells accept a -c
command line option that lets you pass in a string to execute - I guess you'll just have to assume that as being the common interface for whatever shell the user has chosen.
Once you have the user's environment, you can then grab their list of paths out of that, and do the search for whatever executable you're looking for from that. Like I said, I really don't know whether this is worth the trouble, but that's the direction I would go if I were implementing this.
Related to Brian Webster's answer:
An easier way to get the User's shell is to use the NSProcessInfo class. e.g
NSDictionary *environmentDict = [[NSProcessInfo processInfo] environment];
NSString *shellString = [environmentDict objectForKey:@"SHELL"];
Which is easier than using dscl and parsing XML input.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With