Monday, June 26, 2006

Legacy StartupItems (OSXvnc)

Even though the current version of OS X deprecates StartupItems in favor of launchd, StartupItems are still supported, and some applications still use this mechanism for starting services. OSXvnc is one example.

StartupItems are analogous to the files found under init.d (or rc*.d) in operating systems that use System-V-style service-startup scripts. As with SysV init scripts, the application developer is expected to provide a script which will accept a few conventional command line arguments such as "start", "stop" and maybe "restart". The operating system then invokes the script with the appropriate argument to manage the service in question.

StartupItems provide an additional ability to control the order in which services are started. This is accomplished by listing tokens that are either "required" or "provided" by a given service. If a particular token is required to start a given service, the operating system will first start whatever other service provides that token.

As you'd expect, this meta-information about the service is provided in a Property List (plist) file. Each StartupItems service has an associated StartupParameters.plist file. In the case of OSXvnc, the file looks like this:

{
Description = "VNC Server";
Provides = ("VNC");
Requires = ("Resolver");
Uses = ("Core Graphics");
OrderPreference = "None";
Messages = {
restart = "Restarting OSXvnc server";
start = "Starting OSXvnc server";
stop = "Stopping OSXvnc server";
};
}

Note that this is an old-style, non-XML plist file. I'm not sure if this is a requirement for StartupItems, but all of the examples I've seen use this format.

The file says that the OSXvnc service will provide the token "VNC" (for potential use by other services that may depend on OSXvnc being running before they are started) and that it requires the token "Resolver" (meaning that the OSXvnc service should not be started until after the resolver service has started). The "Uses" property is similar to "Requires", but it specifies optional services. The operating system will try to start the list of services in the "Uses" property, but OSXvnc will still start even if these other services fail. Finally, an "OrderPreference" property can be used to fine-tune the startup order of services. Allowed values are First, Early, None, Late, or Last.

The operating system looks for StartupItem services in /System/Library/StartupItems and /Library/StartupItems. The former is for use by services provided by Apple, and the latter is for use by the local administrator. The startup order of services isn't affected by which directory the startup item is located in.

In addition to the plist file, you'll also need the "init" script mentioned above. The plist file and the init script for each service reside in a subdirectory of /System/Library/StartupItems or /Library/StartupItems. In the case of OSXvnc, this directory is /Library/StartupItems/OSXvnc. In the subdirectory should be an appropriate StartupParameters.plist file and an executable file (the init script) with the same name as the directory. Any other programs or data files needed by the service may also be located here.

At startup time, the operating system crawls through the subdirectories of /System/Library/StartupItems and /Library/StartupItems, looks at the "requires" and "provides" for each service, then builds up an ordered list of services to start. When it comes to OSXvnc, it will execute the command "/Library/StartupItems/OSXvnc/OSXvnc start" to start the service.
Update: Note that all files and directories from /Library/StartupItems on down must NOT be group- or world-writeable. Otherwise SystemStarter will refuse to run them.

StartupItems can be started/stopped at any time using the "SystemStarter" command. Some usage examples:


SystemStarter start VNC
SystemStarter stop VNC


Note that SystemStarter commands refer to the "Provides" tokens from the service's StartupParameters.plist file, rather than the name of a service's StartupItems directory (i.e., "VNC" versus "OSXvnc", in this case).

Also note that SystemStarter is run at boot time from /etc/rc, which is in turn run from launchd (like everything else).

For more information about StartupItems, see this Mac Developer article and this useful article at MacDevCenter.

No comments: