I'm attempting to configure Upstart to run a small utility that needs to access a tty as a system-wide daemon. When run from the command-line, the utility remains in the foreground and doesn't exit until a Ctrl+C; I've therefore omitted the expect stanza and Upstart is correctly tracking the PID. I've also created an unprivileged account for the daemon using adducer --system --no-create-home --disabled-login avrlirc.
On my system, the tty the utility needs to access is installed as:
crw-rw---- 1 root dialout 166, 0 May 24 19:25 ttyACM0
So I added the user avrlirc (created above) to the dialout group. When I run the utility as avrlirc everything works as expected. I added the stanza setuid avrlirc to the Upstart configuration file, and the job fails with "can't open tty".
If I omit the setuid stanza, it works (so it's likely a permissions thing). If I add the setgid dialout stanza alongside the setuid, it also works.
So, why do I need setgid when I already have setuid and the user is a member of the appropriate group—why isn't that enough?
For reference, the Upstart job config file is:
start on runlevel [2345]
stop on runlevel [016]
console log
setuid avrlirc
setgid dialout
exec /usr/local/bin/avrlirc2udp -f -H -h <IP_ADDRESS> -t /dev/ttyACM0
Where <IP_ADDRESS> is the IPv4 address of the local box and within 192.168.0.0/16.
avrlirc2udp(details), which accepts serial input from an Arduino Uno with IR receiver and sends it on to LIRC via UDP. – Calrion May 25 '12 at 3:02