November 2008 (using Leopard 10.5.5)

PATH and other evironment issues in Leopard

PATH and path_helper

Leopard introduced this great(?) new way of setting up default PATH and and MANPATH, in /usr/libexec/path_helper. Some people don't like it much, but I think it's not bad, and it's perfectly workable once you understand all of the issues.

The idea is simple. /etc/paths contains the initial PATH values, one path per line, in order. /etc/paths.d contains additional files, with paths to be added to your PATH. They'll be added based on the sort order of the filenames there. This does make me wish they'd called the one default file in there 50_X11, instead of X11, so that they'd created a precedent of numbering things in desired order. But they didn't. You can change it, or you can add other prefixes to anything you add there. It's also worth mentioning that if a path is repeated in more than one place, it is NOT added more than once. The first location wins.

But how does it really work?

First of all, path_helper seem to be run exclusively out of /etc/profile and /etc/csh.login. This means that for things that are not login shells, path_helper is NOT run (for both types of shell). An example would be starting an xterm with +ls, or running a command in ssh (e.g. 'ssh hostname who'). However /etc/bashrc, or /etc/csh.cshrc are still both run for interactive shells, and so ar the user's .bashrc or .cshrc files. So if the user customizes their PATH in these files, these changes will still show up.

Of course a shell which is not interactive (e.g. a script) shouldn't read ANY of these files, and in that case it will simply get the initial default PATH. But sh and csh behave differently. If there is no PATH at all, sh/bash uses a compiled-in PATH of "/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:." (as of Leopard 10.5.5). csh/tcsh does not use a compiled-in PATH, but it DOES source /etc/csh.cshrc, and $HOME/.cshrc. Yes that's right, these are sourced even when running shell scripts (c.f. "use of csh considered harmful").

Second of all, /etc/paths does not actually contain initial PATH values. You can prove this by removing this file, and noting that you don't get rid of these paths (except for /usr/local/bin). /etc/paths does contain paths that are added first, but they are ADDED to the current PATH, they don't replace it. The initial PATH of "/usr/bin:/bin:/usr/sbin:/sbin" seems to be hardcoded in /sbin/launchd. This means that anything you want to set as a true default initial starting PATH, is best set in /etc/profile and /etc/csh.login, before the call to path_helper. In my case, I wanted to take out the sbin directories (these directories should contain commands for admins, not for general users).

Third, X11 is special. If you just run "xterm" from a Terminal window, Leopard very cooly automatically starts up X11, but it won't be that surprising that the xterm that runs inherits the environment from the Terminal window. But there's still some funky stuff going on. The script /usr/X11/bin/startx adds two things to your path, if they aren't there already; /usr/X11/bin gets added to the beginning of your path, and /usr/X11R6/bin gets added to the end of your path. This is kind of stupid since under Leopard these are both the same directory. But the other weird thing is that startx is started by /System/Library/LaunchAgents/org.x.startx.plist (which isn't the weird part). If you peek in there, you'll notice that it explicitly calls this script by calling bash with the --login option. What this means is that X11 gets started using /etc/profile, and hence path_helper. And what THIS means is that an xterm started with command-N (⌘-N) may have a different environment (inherited from X11) than if you start xterm from the command line in a Terminal window.

(Feb '09) One more thing I've found about X11. When you start X11 by clicking on the X11 icon, it (by default) starts an xterm too. But the xterm started here is not a child of X11, it's started in parallel, and it is started without using the path_helper stuff. So it won't have the same system-supplied environment that any subsequent applications started by X11 will have.

To fully control the user's PATH, I'd suggest setting it to empty in /etc/profile and /etc/csh.login immediately before path_helper is called, and then use the mechanism they provide to give an initial path in /etc/paths, and then provide path packages in /etc/paths.d BUT in light of the weird xterm problem described above, perhaps scrapping the whole thing and doing traditional user dot file setup is the way to go.

Cron jobs are a whole 'nother thing too, and maybe I'll get into that at some point.


MANPATH can be controlled in the same way that PATH can. The parallel files /etc/manpaths and /etc/manpaths.d/* exist, and work just the same. I don't think launchd provides any default values, so whatever is in /etc/manpaths really does work out to be the default.

However, man can also be configured using /etc/man.conf. But much of this file is ignored if MANPATH is set. If you prefer /etc/man.conf, then my suggestion would be to either clear out /etc/manpaths and /etc/manpaths.d/*, or just remove the variable MANPATH after path_helper is called in /etc/profile and /etc/csh.login ("unset MANPATH" for sh/bash, and "unsetenv MANPATH" for csh/tcsh).

X11 environment

You may notice that you can start any X11 command, and that causes X11 itself to start -- one of the cute uses of launchd. But for this to work, the DISPLAY environment variable must be set even though X11 isn't running. This is set by launchd, but not the process ID 1 system launchd that functions like init on other Unix systems. When you log in, the system starts a user-level launchd, and this is what sets your DISPLAY variable, and handles the as-needed launching of X11. This has some important ramifications in configuring X11.

So far the only X11 config I've had to do was for MacPorts and Fink. If you add either or both of these, you'll find that those X11-based applications may not find the app-defaults files that they came with. The problem is that the default search path, which seems to be compiled in to libXt, doesn't look in the new locations. Environment variables XFILESEARCHPATH and XUSERFILESEARCHPATH can be used to tell libXt where to look.

I haven't found an excellent solution here. I add to the user's startup files that if they're on a Darwin system, they get the variable XUSERFILESEARCHPATH set to "/opt/local/lib/X11/app-defaults/%N:/sw/etc/app-defaults/%N". Note that one really strange gotcha here is that other percent-things (like %T) don't work here, so a path that WOULD work in XFILESEARCHPATH will NOT work in XUSERFILESEARCHPATH. Apparently this wierdness is true on all platforms, not just OS X.

You can't really add this to /usr/X11/bin/startx. In a traditional environment this would be ok, because most X11 clients are descendenants of the X server. Because of the launchd tricks, this isn't true on Leopard. You can start X things from anywhere that's a child of the user-level launchd. In practice this will probably just be shells, so you really want your default dot files to set up this environment. It would be great if there was some file where you could configure variables set by launchd, or (specific to this case), if there was a file where you could configure the libXt search paths.

In a more perfect world

It'd be nice if I could put group-readable files into /etc/paths.d, and only members of that group would get that path. This does in fact work if you are willing to live with "Permission denied" error messages for all users not in those groups.

Even cooler would be a subscription-based thing. Default system files would have things like "subscribe core,x11,fink", and this would take care of all variables for those packages in one swoop. Then the user could do things like "unsubscribe fink; subscribe admin,macports" to alter their entire environment from the default. By the way, I'm pretty sure this idea was suggested to me about 20 years ago by J Greely, and who knows where he got it. [an error occurred while processing this directive]

More Mac OS X Stuff

Tom Fine's Home
Send Me Email