aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2024 Wojtek Kosior <koszko@koszko.org>
;;; Additions and modifications by Wojtek Kosior are additionally
;;; dual-licensed under the Creative Commons Zero v1.0.
;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu system accounts)
  #:use-module (guix records)
  #:use-module (ice-9 match)
  #:use-module (ice-9 vlist)
  #:use-module (srfi srfi-8)
  #:use-module (srfi srfi-26)
  #:export (user-account
            user-account?
            user-account-name
            user-account-password
            user-account-uid
            user-account-group
            user-account-supplementary-groups
            user-account-comment
            user-account-home-directory
            user-account-create-home-directory?
            user-account-shell
            user-account-system?

            user-group
            user-group?
            user-group-name
            user-group-password
            user-group-id
            user-group-system?

            user-extra-groups
            user-extra-groups?
            user-extra-groups-user
            user-extra-groups-groups

            merge-extra-groups-data

            subid-range
            subid-range?
            subid-range-name
            subid-range-start
            subid-range-count
            subid-range-end
            subid-range-has-start?
            subid-range-less

            sexp->user-account
            sexp->user-group
            sexp->subid-range

            default-shell))


;;; Commentary:
;;;
;;; Data structures representing user accounts and user groups.  This is meant
;;; to be used both on the host side and at run time--e.g., in activation
;;; snippets.
;;;
;;; Code:

(define default-shell
  ;; Default shell for user accounts (a string or string-valued gexp).
  (make-parameter "/bin/sh"))

(define-record-type* <user-account>
  user-account make-user-account
  user-account?
  (name           user-account-name)
  (password       user-account-password (default #f))
  (uid            user-account-uid (default #f))
  (group          user-account-group)             ; number | string
  (supplementary-groups user-account-supplementary-groups
                        (default '()))            ; list of strings
  (comment        user-account-comment (default ""))
  (home-directory user-account-home-directory (thunked)
                  (default (default-home-directory this-record)))
  (create-home-directory? user-account-create-home-directory? ;Boolean
                          (default #t))
  (shell          user-account-shell              ; gexp
                  (default (default-shell)))
  (system?        user-account-system?            ; Boolean
                  (default #f)))

(define-record-type* <user-group>
  user-group make-user-group
  user-group?
  (name           user-group-name)
  (password       user-group-password (default #f))
  (id             user-group-id (default #f))
  (system?        user-group-system?              ; Boolean
                  (default #f)))

(define-record-type* <user-extra-groups> user-extra-groups
  make-user-extra-groups
  user-extra-groups?
  (user           user-extra-groups-user)
  (groups         user-extra-groups-groups))      ; list of strings

(define (user-account-extend account extra-groups)
  (match-record account <user-account> (name supplementary-groups)
    (user-account
     (inherit account)
     (supplementary-groups (apply append supplementary-groups
                                  (vhash-fold* cons '()
                                               name extra-groups))))))

(define (merge-extra-groups-data accounts-data)
  (let* ((extra-groups-alist (map (match-record-lambda <user-extra-groups>
                                      (user groups)
                                    (cons user groups))
                                  (filter user-extra-groups? accounts-data)))
         (extra-groups (alist->vhash extra-groups-alist))
         (user-accounts (map (cut user-account-extend <> extra-groups)
                             (filter user-account? accounts-data)))
         (other-records (filter (lambda (record)
                                  (not (or (user-account? record)
                                           (user-extra-groups? record))))
                                accounts-data)))
    (append other-records user-accounts)))

(define-record-type* <subid-range>
  subid-range make-subid-range
  subid-range?
  (name           subid-range-name)
  (start          subid-range-start (default #f))    ; number
  (count          subid-range-count                  ; number
                  ; from find_new_sub_gids.c and
                  ; find_new_sub_uids.c
                  (default 65536)))

(define (subid-range-end range)
  "Returns the last subid referenced in RANGE."
  (and
   (subid-range-has-start? range)
   (+ (subid-range-start range)
      (subid-range-count range)
      -1)))

(define (subid-range-has-start? range)
  "Returns #t when RANGE's start is a number."
  (number? (subid-range-start range)))

(define (subid-range-less a b)
  "Returns #t when subid range A either starts before, or is more specific
than B.  When it is not possible to determine whether a range is more specific
w.r.t. another range their names are compared alphabetically."
  (define start-a (subid-range-start a))
  (define start-b (subid-range-start b))
  (cond ((and (not start-a) (not start-b))
         (string< (subid-range-name a)
                  (subid-range-name b)))
        ((and start-a start-b)
         (< start-a start-b))
        (else
         (and start-a
              (not start-b)))))

(define (default-home-directory account)
  "Return the default home directory for ACCOUNT."
  (string-append "/home/" (user-account-name account)))

(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?)))))

(define (sexp->subid-range sexp)
  "Take SEXP, a tuple as returned by 'subid-range->gexp', and turn it into a
subid-range record."
  (match sexp
    ((name start count)
     (subid-range (name name)
                  (start start)
                  (count count)))))
dex): New procedures. (syntax-highlighted-html): Add #:mono-node-indexes and #:split-node-indexes. [build](underscore-decode, anchor-id->key, collect-anchors): Remove. (language+node-anchors, mono-node-anchors, multi-node-anchors): New variables. Use them. Ludovic Courtès 2020-10-17doc: Remove 'build.scm' from the source of the manual....That way we no longer have to rebuild the whole manual when fiddling with 'build.scm'. * doc/build.scm <top level>: Define 'select?' and pass it to 'pdf+html-manual'. Ludovic Courtès 2020-09-04doc: Syntax highlighting now handles @var within @lisp....* doc/build.scm (syntax-highlighted-html)[build](concatenate-pieces): Handle @var{name}. Ludovic Courtès 2020-05-25doc: Remove one use of 'file-append*'....* doc/build.scm (texinfo-manual-source)[build]: Use 'file-append', not 'file-append*', for 'htmlxref.cnf', to ensure it has the right basename. Ludovic Courtès 2020-05-18doc: Inherit md5.scm fix in custom 'guile-lib' variant....* doc/build.scm (guile-lib/htmlprag-fixed)[source]: Remove. [arguments]: Add 'fix-htmlprag' phase. Ludovic Courtès 2020-05-02doc: Fix building the cookbook....Fixes <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=40803>. Reported by "operator.name" <operator.name@protonmail.com>. * doc/build.scm (%languages): Add smaller list for the cookbook. (syntax-highlighted-html): Adapt regexp for mono-node files to include the cookbook. Björn Höfling 2020-04-21doc: Include *.json files in the source....This is a followup to c9f321e52a99dea93fcc099372ea0167150b9aac. * doc/build.scm (texinfo-manual-source)[build]: Add *.json to #$output. Ludovic Courtès 2020-04-13doc: Improve anchor collection....This allows us to catch "operating_002dsystem-1", for instance. * doc/build.scm (syntax-highlighted-html)[build](anchor-id->key): Drop "-1" & co. from ID. Ludovic Courtès 2020-04-13doc: Avoid invalid 'match' pattern in 'syntax-highlighted-html'....This is a followup to da9deba13d551e316f5a99a614834efa27ddc7d1. Last-minute modification of the 'match' pattern would lead to an error: "multiple ellipsis patterns not allowed at same level" * doc/build.scm (syntax-highlighted-html)[build](collect-anchors): Add 'worthy-entry?' procedure and use it instead of the unsupported pattern for ('dt ...). Ludovic Courtès 2020-04-13doc: Emit hyperlinks in HTML output for @lisp snippets....This makes it easier to jump to the definition of a procedure or variable when looking at a code snippet. There can be false-positive because scoping rules are ignored, for example, but it should be a good approximation. * doc/build.scm (syntax-highlighted-html)[build](highlights->sxml*): Add 'anchors' parameter. Add clause for ('symbol text). (syntax-highlight): Add 'anchors' parameter. Wrap body in named let and use it in recursive calls. Pass ANCHORS to 'highlights->sxml*'. (underscore-decode, anchor-id->key, collect-anchors, html?): New procedures. (process-file): Add 'anchors' parameter. and honor it. Rewrite mono-node and multi-node HTML files separately. Ludovic Courtès 2020-01-12doc: Make sure 'htmlxref.cnf' is honored....Fixes <https://bugs.gnu.org/39060>. Reported by Tobias Geerinckx-Rice <me@tobias.gr>. * doc/build.scm (html-manual)[build]: Copy 'htmlxref.cnf' to the current directory so that 'makeinfo' honors it. Ludovic Courtès 2019-11-28doc: Handle right arrows in 'syntax-highlighted-html'....* doc/build.scm (syntax-highlighted-html)[build](entity->string): Add "rarr". Ludovic Courtès 2019-10-22doc: Use the right title in HTML indices for the cookbook....* doc/build.scm (html-manual-indexes): Add #:title. [build]: Replace "GNU Guix Reference Manual" by references to TITLE. Ludovic Courtès 2019-10-21doc: More responsive online manual....* doc/build.scm (%makeinfo-html-options): Add viewport to all generated html pages for better mobile device support. Julien Lepiller 2019-10-21doc: Add support for "guix-cookbook.texi" to 'build.scm'....* doc/build.scm (%manual): New variable. (html-manual): #:manual now defaults to %MANUAL. [build]: Define 'language->texi-file-name' and use it. Filter out items of LANGUAGES that lack a .texi file. (pdf-manual, html-manual-indexes, pdf+html-manual): #:manual now defaults to %MANUAL. Ludovic Courtès 2019-09-25doc: Support paren matching via CSS hover....* doc/build.scm (syntax-highlighted-html)[build](pair-open/close) (highlights->sxml*): New procedures. (syntax-highlight): Use 'highlights->sxml*'. Ludovic Courtès 2019-09-07doc: Work around (htmlprag) parser issue....* doc/build.scm (guile-lib/htmlprag-fixed): New variable. (syntax-highlighted-html): Use it instead of GUILE-LIB. Ludovic Courtès 2019-09-07doc: Highlight Scheme syntax in the HTML output....* doc/build.scm (syntax-highlighted-html): New procedure. (html-manual): Use it. Ludovic Courtès 2019-07-16doc: Add 'images' directory next to HTML pages....* doc/build.scm (html-manual): Add images/ symlinks. Ludovic Courtès 2019-07-15doc: Build a top-level index of the manuals....Suggested by Julien Lepiller. * doc/build.scm (html-manual-indexes)[build]: Add 'with-extensions'. (translate): Actually honor DOMAIN. Add call to 'bindtextdomain' for ISO-CODES. (%iso639-languages): New variable. (language-code->name, top-level-index): New procedures. Add call to 'write-html' for OUTPUT/index.html. Ludovic Courtès 2019-07-15doc: Generalize build procedures of HTML indexes....* doc/build.scm (html-manual-indexes)[build](sxml-index): Generalize; add a 'title' and a 'body' parameter and honor them. (language-index): New procedure. (write-index): Remove. (write-html): New procedure. Use 'write-html' and 'language-index'. Ludovic Courtès 2019-07-07build: Add 'doc/build.scm' to build on-line copies of the manual....* doc/build.scm: New file. * Makefile.am (EXTRA_DIST): Add it. Ludovic Courtès