1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| | diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index bd7e379..2344915 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -758,6 +758,28 @@ daemon writing FILE is running in a separate PID namespace."
(try-again)
(apply throw args)))))))
+(define (supplementary-gids user)
+ "Return a vector with the gid for each supplementary group USER belongs to.
+USER is the user name as a string."
+ ;; TODO: To find them, we loop through the group database, but maybe using
+ ;; glibc’s getgrouplist would be better. But it is not exported from Guile
+ ;; and it seems it is not part of POSIX (?).
+ (list->vector
+ (delete-duplicates
+ (dynamic-wind
+ (lambda () (setgrent))
+ (lambda ()
+ (let loop ((supgids '()))
+ (let ((group (getgrent)))
+ (define (user-among-group? group)
+ (member user (group:mem group)))
+ (match group
+ (#f supgids)
+ ((? user-among-group?)
+ (loop (cons (group:gid group) supgids)))
+ (else (loop supgids))))))
+ (lambda () (endgrent))))))
+
(define* (exec-command command
#:key
(user #f)
@@ -826,7 +848,8 @@ false."
(when user
(catch #t
(lambda ()
- (setuid (passwd:uid (getpw user))))
+ (setuid (passwd:uid (getpw user)))
+ (setgroups (supplementary-gids user)))
(lambda (key . args)
(format (current-error-port)
"failed to change to user ~s:~%" user)
|