Is there a way of changing (unix) user? I can see getpid in the racket/os package, and if a setuid-a-like function exists, I'd expect to find it nearby, but I can't find it there or under any other search string I can think of.
Why? I'm trying to see if fork+setuid looks reasonably neat in a server program. The right thing to do is probably to use daemon or equivalent, but there are a couple of intricacies with that, and rather than fight with it I thought I'd look to see if doing it 'by hand' would be simpler in the long run.
The FFI had occurred to me, but the fact that this wasn't in the racket/os module, where it seems an obvious member of the collection of random other OS facilities I'd expect to find there, made me think I was missing something thoughtful elsewhere.
It's slightly surprising that I can't do this in a library-standard way, but if I'm assured it's not there, then I can just stick with Plan A.
@nxg My guess is racket/os is intended to be portable but setuid isn't.
So for example its getpid (1) just gets (2) some unique integer for the process. Even if some OS returned (say) a unique string instead of number ID, you could imagine implementing this to honor the contract.
Whereas that FFI example linked to by @bakgatviooldoos suggests "setuid" isn't portable:
(require (prefix-in ffi: ffi/unsafe))
...
; allow Arc to give up root privileges after it
; calls open-socket. thanks, Eli!
(define setuid (ffi:get-ffi-obj 'setuid #f
(ffi:_fun ffi:_int ffi:-> ffi:_int)
; If we're on Windows, there is no setuid, so we make
; a dummy version. See "Arc 3.1 setuid problem on
; Windows," http://arclanguage.org/item?id=10625.
(lambda () (lambda (x) 'nil))))
I'm guessing that although Windows surely has some notion of a "user ID", it might lack the ability of a process to change this for itself? (I don't think running as root and dropping privileges is really part of the Windows history/culture.)
Anyway, although the FFI "DSL" can take awhile to learn for complicated examples, as you can see it can be pretty painless in simple cases like this.
If possible, I recommend avoiding setuid by launching your program as an unprivileged user and only granting it the capabilities it actually needs. On a typical GNU/Linux system, you can allow an unprivileged process to bind to "privileged" ports (< 1024) by granting it the CAP_NET_BIND_SERVICE capability, for example by adding the following to your systemd unit file:
[quote="greghendershott, post:5, topic:2766"]
I'm guessing that although Windows surely has some notion of a "user ID", it might lack the ability of a process to change this for itself? (I don't think running as root and dropping privileges is really part of the Windows history/culture.)[/quote]
It looks like you're right – thanks – and that makes a lot of sense.
I've been spoilt here, recently, by spending time with s7 which, as an extension language is, in a sense, all-FFI. It's a rather ascetic experience, as Schemes go, but the FFI is sweet.
Yes, that's my Plan A, really – it's an excellent suggestion.
I'm using daemon invoked from rc.d (this won't be running on a systemd box), but I think I'm slightly fumbling the invocation, and rather than read the manpage yet again, I (slightly self-indulgently) wondered if doing this the old-skool way might be simpler. I'm not surprised it's not: the last time I did this by hand I remember discovering how many moving parts there are to get subtly wrong.
I remain slightly surprised that Racket doesn't have a portable implementation of the daemonise operation, but since things like systemd and /usr/sbin/daemon exist and do work, there isn't, when it comes down to it, a clearly demonstrable need for it.