From patchwork Mon Mar 4 11:16:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ludovic_Court=C3=A8s?= X-Patchwork-Id: 1285 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id B61B416CF6; Mon, 4 Mar 2019 11:17:18 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTP id 197FC16C43 for ; Mon, 4 Mar 2019 11:17:18 +0000 (GMT) Received: from localhost ([127.0.0.1]:52088 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h0lav-0002KJ-M9 for patchwork@mira.cbaines.net; Mon, 04 Mar 2019 06:17:17 -0500 Received: from eggs.gnu.org ([209.51.188.92]:36244) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h0lai-0002H0-Q5 for guix-patches@gnu.org; Mon, 04 Mar 2019 06:17:06 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h0lah-0000X9-4j for guix-patches@gnu.org; Mon, 04 Mar 2019 06:17:04 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:45487) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h0lag-0000WR-Vd for guix-patches@gnu.org; Mon, 04 Mar 2019 06:17:03 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1h0lag-0006HI-QK for guix-patches@gnu.org; Mon, 04 Mar 2019 06:17:02 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#34730] [PATCH 2/4] activation: Operate on and records. Resent-From: Ludovic =?utf-8?q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Mon, 04 Mar 2019 11:17:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 34730 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 34730@debbugs.gnu.org Received: via spool by 34730-submit@debbugs.gnu.org id=B34730.155169821524090 (code B ref 34730); Mon, 04 Mar 2019 11:17:02 +0000 Received: (at 34730) by debbugs.gnu.org; 4 Mar 2019 11:16:55 +0000 Received: from localhost ([127.0.0.1]:59025 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h0laY-0006GI-Uu for submit@debbugs.gnu.org; Mon, 04 Mar 2019 06:16:55 -0500 Received: from hera.aquilenet.fr ([185.233.100.1]:34610) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h0laW-0006G0-L2 for 34730@debbugs.gnu.org; Mon, 04 Mar 2019 06:16:53 -0500 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 1FC409B02; Mon, 4 Mar 2019 12:16:52 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9URXH4t5iLBb; Mon, 4 Mar 2019 12:16:50 +0100 (CET) Received: from gnu.org (unknown [IPv6:2001:660:6102:320:e120:2c8f:8909:cdfe]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 427AF9B04; Mon, 4 Mar 2019 12:16:50 +0100 (CET) From: Ludovic =?utf-8?q?Court=C3=A8s?= Date: Mon, 4 Mar 2019 12:16:42 +0100 Message-Id: <20190304111644.8573-2-ludo@gnu.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190304111644.8573-1-ludo@gnu.org> References: <20190304111644.8573-1-ludo@gnu.org> MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: "Guix-patches" X-getmail-retrieved-from-mailbox: Patches * gnu/system/accounts.scm (sexp->user-group, sexp->user-account): New procedures. * gnu/system/shadow.scm (account-activation): Call them in the arguments to 'activate-users+groups'. (account-shepherd-service): Likewise. * gnu/build/activation.scm (activate-users+groups): Expect a list of and a list of . Replace uses of 'match' on tuples with calls to record accessors. (activate-user-home): Likewise. --- gnu/build/activation.scm | 118 ++++++++++++++++++++------------------- gnu/system/accounts.scm | 28 ++++++++++ gnu/system/shadow.scm | 22 +++++--- 3 files changed, 103 insertions(+), 65 deletions(-) diff --git a/gnu/build/activation.scm b/gnu/build/activation.scm index 0e77677de1..820e04d648 100644 --- a/gnu/build/activation.scm +++ b/gnu/build/activation.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès +;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès ;;; Copyright © 2015 Mark H Weaver ;;; ;;; This file is part of GNU Guix. @@ -18,6 +18,7 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu build activation) + #:use-module (gnu system accounts) #:use-module (gnu build linux-boot) #:use-module (guix build utils) #:use-module (ice-9 ftw) @@ -212,37 +213,42 @@ logged in." (apply add-user name group rest))) (define (activate-users+groups users groups) - "Make sure the accounts listed in USERS and the user groups listed in GROUPS -are all available. - -Each item in USERS is a list of all the characteristics of a user account; -each item in GROUPS is a tuple with the group name, group password or #f, and -numeric gid or #f." + "Make sure USERS (a list of user account records) and GROUPS (a list of user +group records) are all available." (define (touch file) (close-port (open-file file "a0b"))) (define activate-user - (match-lambda - ((name uid group supplementary-groups comment home create-home? - shell password system?) - (let ((profile-dir (string-append "/var/guix/profiles/per-user/" - name))) - (ensure-user name group - #:uid uid - #:system? system? - #:supplementary-groups supplementary-groups - #:comment comment - #:home home - #:create-home? create-home? + (lambda (user) + (let ((name (user-account-name user)) + (uid (user-account-uid user)) + (group (user-account-group user)) + (supplementary-groups + (user-account-supplementary-groups user)) + (comment (user-account-comment user)) + (home (user-account-home-directory user)) + (create-home? (user-account-create-home-directory? user)) + (shell (user-account-shell user)) + (password (user-account-password user)) + (system? (user-account-system? user))) + (let ((profile-dir (string-append "/var/guix/profiles/per-user/" + name))) + (ensure-user name group + #:uid uid + #:system? system? + #:supplementary-groups supplementary-groups + #:comment comment + #:home home + #:create-home? create-home? - #:shell shell - #:password password) + #:shell shell + #:password password) - (unless system? - ;; Create the profile directory for the new account. - (let ((pw (getpwnam name))) - (mkdir-p profile-dir) - (chown profile-dir (passwd:uid pw) (passwd:gid pw)))))))) + (unless system? + ;; Create the profile directory for the new account. + (let ((pw (getpwnam name))) + (mkdir-p profile-dir) + (chown profile-dir (passwd:uid pw) (passwd:gid pw)))))))) ;; 'groupadd' aborts if the file doesn't already exist. (touch "/etc/group") @@ -251,18 +257,18 @@ numeric gid or #f." (mkdir-p "/var/lib") ;; Create the root account so we can use 'useradd' and 'groupadd'. - (activate-user (find (match-lambda - ((name (? zero?) _ ...) #t) - (_ #f)) - users)) + (activate-user (find (compose zero? user-account-uid) users)) ;; Then create the groups. - (for-each (match-lambda - ((name password gid system?) - (unless (false-if-exception (getgrnam name)) - (add-group name - #:gid gid #:password password - #:system? system?)))) + (for-each (lambda (group) + (let ((name (user-group-name group)) + (password (user-group-password group)) + (gid (user-group-id group)) + (system? (user-group-system? group))) + (unless (false-if-exception (getgrnam name)) + (add-group name + #:gid gid #:password password + #:system? system?)))) groups) ;; Create the other user accounts. @@ -272,35 +278,33 @@ numeric gid or #f." (for-each delete-user (lset-difference string=? (map passwd:name (current-users)) - (match users - (((names . _) ...) - names)))) + (map user-account-name users))) (for-each delete-group (lset-difference string=? (map group:name (current-groups)) - (match groups - (((names . _) ...) - names))))) + (map user-group-name groups)))) (define (activate-user-home users) "Create and populate the home directory of USERS, a list of tuples, unless they already exist." (define ensure-user-home - (match-lambda - ((name uid group supplementary-groups comment home create-home? - shell password system?) - ;; The home directories of system accounts are created during - ;; activation, not here. - (unless (or (not home) (not create-home?) system? - (directory-exists? home)) - (let* ((pw (getpwnam name)) - (uid (passwd:uid pw)) - (gid (passwd:gid pw))) - (mkdir-p home) - (chown home uid gid) - (unless system? - (copy-account-skeletons home - #:uid uid #:gid gid))))))) + (lambda (user) + (let ((name (user-account-name user)) + (home (user-account-home-directory user)) + (create-home? (user-account-create-home-directory? user)) + (system? (user-account-system? user))) + ;; The home directories of system accounts are created during + ;; activation, not here. + (unless (or (not home) (not create-home?) system? + (directory-exists? home)) + (let* ((pw (getpwnam name)) + (uid (passwd:uid pw)) + (gid (passwd:gid pw))) + (mkdir-p home) + (chown home uid gid) + (unless system? + (copy-account-skeletons home + #:uid uid #:gid gid))))))) (for-each ensure-user-home users)) diff --git a/gnu/system/accounts.scm b/gnu/system/accounts.scm index 36ee62e851..eb18fb5e43 100644 --- a/gnu/system/accounts.scm +++ b/gnu/system/accounts.scm @@ -18,6 +18,7 @@ (define-module (gnu system accounts) #:use-module (guix records) + #:use-module (ice-9 match) #:export (user-account user-account? user-account-name @@ -38,6 +39,9 @@ user-group-id user-group-system? + sexp->user-account + sexp->user-group + default-shell)) @@ -79,3 +83,27 @@ (id user-group-id (default #f)) (system? user-group-system? ; Boolean (default #f))) + +(define (sexp->user-group sexp) + "Take SEXP, a tuple as returned by 'user-group->gexp', and turn it into a +user-group record." + (match sexp + ((name password id system?) + (user-group (name name) + (password password) + (id id) + (system? system?))))) + +(define (sexp->user-account sexp) + "Take SEXP, a tuple as returned by 'user-account->gexp', and turn it into a +user-account record." + (match sexp + ((name uid group supplementary-groups comment home-directory + create-home-directory? shell password system?) + (user-account (name name) (uid uid) (group group) + (supplementary-groups supplementary-groups) + (comment comment) + (home-directory home-directory) + (create-home-directory? create-home-directory?) + (shell shell) (password password) + (system? system?))))) diff --git a/gnu/system/shadow.scm b/gnu/system/shadow.scm index a9a4afd414..4e5b6ae5f2 100644 --- a/gnu/system/shadow.scm +++ b/gnu/system/shadow.scm @@ -298,11 +298,14 @@ group." (assert-valid-users/groups accounts groups) ;; Add users and user groups. - #~(begin - (setenv "PATH" - (string-append #$(@ (gnu packages admin) shadow) "/sbin")) - (activate-users+groups (list #$@user-specs) - (list #$@group-specs)))) + (with-imported-modules (source-module-closure '((gnu system accounts))) + #~(begin + (use-modules (gnu system accounts)) + + (setenv "PATH" + (string-append #$(@ (gnu packages admin) shadow) "/sbin")) + (activate-users+groups (map sexp->user-account (list #$@user-specs)) + (map sexp->user-group (list #$@group-specs)))))) (define (account-shepherd-service accounts+groups) "Return a Shepherd service that creates the home directories for the user @@ -322,12 +325,15 @@ accounts among ACCOUNTS+GROUPS." (list (shepherd-service (requirement '(file-systems)) (provision '(user-homes)) - (modules '((gnu build activation))) + (modules '((gnu build activation) + (gnu system accounts))) (start (with-imported-modules (source-module-closure - '((gnu build activation))) + '((gnu build activation) + (gnu system accounts))) #~(lambda () (activate-user-home - (list #$@(map user-account->gexp accounts))) + (map sexp->user-account + (list #$@(map user-account->gexp accounts)))) #f))) ;stop (stop #~(const #f)) (respawn? #f)