# Launchd socket input

command linelaunchd

I am trying to run a network server that is supposed to receive very short newline-terminated udp messages. The service plist looks like this

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.listener</string>
<key>Program</key>
<string>/bin/cat</string>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockType</key>
<string>dgram</string>
<key>SockNodeName</key>
<string>0.0.0.0</string>
<key>SockServiceName</key>
<integer>9999</integer>
</dict>
</dict>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<true/>
</dict>
<key>StandardOutPath</key>
<string>/tmp/test.stdout</string>
</dict>


and it loads and does what it is supposed to do (write message strings to /tmp/test.stdout). However, I fail at replacing /bin/cat with a shell script
that reads the message into a variable and lets me do something with it. I
thought that something like this should work:

#!/bin/sh
echo $MSG  but this appears to block, and so does #!/bin/sh /bin/cat  while #!/bin/sh exec /bin/cat  still works. On the command line all three variants do about the same thing, e.g., $ echo 123 | ./mycat.sh
123


and nothing blocks. Any insight into these subtle differences would be appreciated.

You're almost there. Wrap your first script in a while loop and you are set:

#!/bin/sh

while true; do

The exec approach works because you replace the current shell with /bin/cat. It is the same as calling /bin/cat directly.