Welp, I found the answer after a few more days of research, with the help of a response to this MacWorld post I thought there had to be some way to include multiple ports in the one .plist file, but I couldn't figure it out. You can add an "Alternate Listener" key to ssh.plist for the extra port inside the Sockets scope, such as:
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
(...)
</dict>
<key>Alternate Listeners</key>
<dict>
<key>SockServiceName</key>
<string>ssh-alt</string>
</dict>
</dict>
Notice the ssh-alt string for SockServiceName. The original "Listeners" key remains as is, so you have Listeners and Alternate Listeners. You have two entries in /etc/services for ssh and ssh-alt like:
ssh 22/udp
ssh 22/tcp
ssh-alt 4790/udp
ssh-alt 4790/tcp
which preserves the port 22 internal access and creates access via port 4790 for external use (assuming you disable port 22 and port forward port 4790 on your firewall/router.
The Program
key specifies the file to execute, & the ProgramArguments
key specifies the arguments which will be passed to the executing process. Strictly speaking you can pass whatever arguments you want to a process, but the convention is that the first one should be the name by which the process was invoked, so most programs ignore their first argument.‡ The file to execute is obviously necessary information, but if the Program
key is is missing, launchd pretends it has the same value as the first argument in ProgramArguments
purely as a convenience.
Your first example starts boinccmd & gives it arguments that would be equivalent to the terminal command
--host\ localhost --passwd\ gobbledygook --project\ http://setiathome.berkeley.edu/\ update
which tells boinccmd that you invoked it as "--host localhost" & only passed it two weird arguments.
Your second example separates the arguments correctly, but as Eddie Kelley suggested it needs one inserted at the front. It tells boinccmd that you invoked it as "--host", then passed another six arguments. boinccmd can recognise the last five as being two options, but has no idea what the "localhost" business is about. As far as boinccmd can tell, it was invoked from the terminal as
/Library/Application\ Support/BOINC\ Data/boinccmd localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update
(note the missing "--host").
boinccmd is probably one of the great majority of programs that don't care what their first argument is, so you could probably actually just shove <string>HELLO</string>
at the head of the ProgramArguments
array, but it's probably cleaner to remove the Program
key altogether & just use this:
<key>ProgramArguments</key>
<array>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<string>--host</string>
<string>localhost</string>
<string>--passwd</string>
<string>gobbledygook</string>
<string>--project</string>
<string>http://setiathome.berkeley.edu/</string>
<string>update</string>
</array>
‡ It can seem like a meaningless redundancy, but some programs use this to good effect: bash et al. act as login shells if their first argument begins with -
, & Vim enters various emulation modes if its first argument is ed
or vi
instead of vim
.
Best Answer
Plists, or property lists, are just a file format for storing serialized objects - for example configurations or similar. The file format specifies how strings are stores, but it doesn't specify anything about higher level details - such as how file names are stored, parsed or otherwise dealt with.
This means that it is not possible to answer your question in general for plists.
The interpretation of $HOME, ~ and environment variables in general in plists are thus application specific. For some programs, it could work - for others it wouldn't. Depends entirely on how that program was made.
UPDATE: You have changed your question to be about LaunchDaemons specifically, and not about plists in general.
For
/Library/LaunchDaemons/startup.plist
it is not possible to refer directly to the environment variables you mention. They're not parsed and replaced with values by launchd. In addition it probably wouldn't have worked like you thought even if they were, because LaunchDaemons are run by root if nothing else is specified.What you can do is refer a program in the
startup.plist
that when run can access the environment and do the variable substitution for you. For example like this: