From c8fa34265d6612c99fe80adfaa66edaddd4d5b0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@gnu.org>
Date: Fri, 25 Jul 2014 00:12:35 +0200
Subject: [PATCH] system: Add the 'system?' field for user groups.

Suggested by Mark H. Weaver.

* gnu/system/shadow.scm (<user-group>)[system?]: New field.
  (%base-groups): Introduce 'system-group' macro, and use it.
* gnu/system.scm (user-group->gexp): Pass the 'system?' field.
* guix/build/activation.scm (add-group): Add #:system? and honor it.
  (activate-users+groups): Handle the 'system?' field.
* gnu/system/file-systems.scm (%tty-gid): Choose an ID below 1000.
* doc/guix.texi (User Accounts): Document the 'system?' field.
---
 doc/guix.texi               |  4 ++++
 gnu/system.scm              |  3 ++-
 gnu/system/file-systems.scm |  2 +-
 gnu/system/shadow.scm       | 42 +++++++++++++++++++++----------------
 guix/build/activation.scm   |  9 +++++---
 5 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 2060da9c554..cef2aba9a83 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3201,6 +3201,10 @@ The group's name.
 The group identifier (a number).  If @code{#f}, a new number is
 automatically allocated when the group is created.
 
+@item @code{system?} (default: @code{#f})
+This Boolean value indicates whether the group is a ``system'' group.
+System groups have low numerical IDs.
+
 @item @code{password} (default: @code{#f})
 What, user groups can have a password?  Well, apparently yes.  Unless
 @code{#f}, this field specifies the group's password.
diff --git a/gnu/system.scm b/gnu/system.scm
index 4648d810a39..68f94386933 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -363,7 +363,8 @@ (define (user-group->gexp group)
 'active-groups'."
   #~(list #$(user-group-name group)
           #$(user-group-password group)
-          #$(user-group-id group)))
+          #$(user-group-id group)
+          #$(user-group-system? group)))
 
 (define (user-account->gexp account)
   "Turn ACCOUNT, a <user-account> object, into a list-valued gexp suitable for
diff --git a/gnu/system/file-systems.scm b/gnu/system/file-systems.scm
index 3b13d820cf9..48c4fc7e773 100644
--- a/gnu/system/file-systems.scm
+++ b/gnu/system/file-systems.scm
@@ -95,7 +95,7 @@ (define %devtmpfs-file-system
 (define %tty-gid
   ;; ID of the 'tty' group.  Allocate it statically to make it easy to refer
   ;; to it from here and from the 'tty' group definitions.
-  1004)
+  996)
 
 (define %pseudo-terminal-file-system
   ;; The pseudo-terminal file system.  It needs to be mounted so that
diff --git a/gnu/system/shadow.scm b/gnu/system/shadow.scm
index e29dbb8c3e6..5d638398d1d 100644
--- a/gnu/system/shadow.scm
+++ b/gnu/system/shadow.scm
@@ -43,6 +43,7 @@ (define-module (gnu system shadow)
             user-group-name
             user-group-password
             user-group-id
+            user-group-system?
 
             default-skeletons
             skeleton-directory
@@ -75,28 +76,33 @@ (define-record-type* <user-group>
   user-group?
   (name           user-group-name)
   (password       user-group-password (default #f))
-  (id             user-group-id (default #f)))
+  (id             user-group-id (default #f))
+  (system?        user-group-system?              ; Boolean
+                  (default #f)))
 
 (define %base-groups
   ;; Default set of groups.
-  (list (user-group (name "root") (id 0))
-        (user-group (name "wheel"))               ; root-like users
-        (user-group (name "users"))               ; normal users
-        (user-group (name "nogroup"))             ; for daemons etc.
+  (let-syntax ((system-group (syntax-rules ()
+                               ((_ args ...)
+                                (user-group (system? #t) args ...)))))
+    (list (system-group (name "root") (id 0))
+          (system-group (name "wheel"))              ; root-like users
+          (system-group (name "users"))              ; normal users
+          (system-group (name "nogroup"))            ; for daemons etc.
 
-        ;; The following groups are conventionally used by things like udev to
-        ;; control access to hardware devices.
-        (user-group (name "tty") (id %tty-gid))
-        (user-group (name "dialout"))
-        (user-group (name "kmem"))
-        (user-group (name "video"))
-        (user-group (name "audio"))
-        (user-group (name "netdev"))              ; used in avahi-dbus.conf
-        (user-group (name "lp"))
-        (user-group (name "disk"))
-        (user-group (name "floppy"))
-        (user-group (name "cdrom"))
-        (user-group (name "tape"))))
+          ;; The following groups are conventionally used by things like udev to
+          ;; control access to hardware devices.
+          (system-group (name "tty") (id %tty-gid))
+          (system-group (name "dialout"))
+          (system-group (name "kmem"))
+          (system-group (name "video"))
+          (system-group (name "audio"))
+          (system-group (name "netdev"))             ; used in avahi-dbus.conf
+          (system-group (name "lp"))
+          (system-group (name "disk"))
+          (system-group (name "floppy"))
+          (system-group (name "cdrom"))
+          (system-group (name "tape")))))
 
 (define (default-skeletons)
   "Return the default skeleton files for /etc/skel.  These files are copied by
diff --git a/guix/build/activation.scm b/guix/build/activation.scm
index 9464d2157df..b04b017881c 100644
--- a/guix/build/activation.scm
+++ b/guix/build/activation.scm
@@ -36,13 +36,14 @@ (define-module (guix build activation)
 ;;;
 ;;; Code:
 
-(define* (add-group name #:key gid password
+(define* (add-group name #:key gid password system?
                     (log-port (current-error-port)))
   "Add NAME as a user group, with the given numeric GID if specified."
   ;; Use 'groupadd' from the Shadow package.
   (format log-port "adding group '~a'...~%" name)
   (let ((args `(,@(if gid `("-g" ,(number->string gid)) '())
                 ,@(if password `("-p" ,password) '())
+                ,@(if system? `("--system") '())
                 ,name)))
     (zero? (apply system* "groupadd" args))))
 
@@ -128,9 +129,11 @@ (define activate-user
 
   ;; Then create the groups.
   (for-each (match-lambda
-             ((name password gid)
+             ((name password gid system?)
               (unless (false-if-exception (getgrnam name))
-                (add-group name #:gid gid #:password password))))
+                (add-group name
+                           #:gid gid #:password password
+                           #:system? system?))))
             groups)
 
   ;; Finally create the other user accounts.
-- 
GitLab