summaryrefslogtreecommitdiff
path: root/pkgtools/pkgtasks/files/users.subr
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkgtasks/files/users.subr')
-rw-r--r--pkgtools/pkgtasks/files/users.subr243
1 files changed, 243 insertions, 0 deletions
diff --git a/pkgtools/pkgtasks/files/users.subr b/pkgtools/pkgtasks/files/users.subr
new file mode 100644
index 00000000000..7734934e5cc
--- /dev/null
+++ b/pkgtools/pkgtasks/files/users.subr
@@ -0,0 +1,243 @@
+# Copyright (c) 2017 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Johnny C. Lam.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# NAME
+# users.subr -- user management for packages
+#
+# SYNOPSIS
+# task_users [-s] add | remove
+# task_users check-add | check-remove
+#
+# DESCRIPTION
+# The task_users function supports four actions: "add", "remove",
+# "check-add", and "check-remove".
+#
+# The available options are as follows:
+#
+# -s Silent; don't write to standard output.
+#
+# The function reads standard input line by line and looks for
+# lines of the form:
+#
+# # USER: <name>:<group>[:<userid>[:<descr>[:<home>[:<shell>]]]]
+#
+# Only the user name and group are required; the remaining fields
+# are optional.
+#
+# The "add" action creates the user with the given name if it is
+# missing, with the given user ID, if ${PKG_CREATE_USERGROUP} is
+# "yes". A reference count for the user will be added for the
+# package.
+#
+# The "remove" action removes a reference count for the user by
+# the package. This function shall not remove any user on the
+# system.
+#
+# The "check-add" action will check whether the users exist with
+# the optional user IDs if they are given, or otherwise writes a
+# message to standard output noting the missing users.
+#
+# The "check-remove" action will check whether the users have been
+# removed, or otherwise writes a message to standard output noting
+# the users still exists.
+#
+# RETURN VALUES
+# The "add" and "remove" actions return 0 if they are successful
+# for all users, and >0 if an error occurs.
+#
+# The "check-add" and "check-remove" actions return >0 if they
+# write informative messages, and return 0 otherwise.
+#
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# PKGNAME
+# The name of the package.
+#
+# PKG_CREATE_USERGROUP
+# If ${PKG_CREATE_USERGROUP} is a "truthy" value, then the
+# "add" and "remove" actions are allowed to create and
+# remove users from the system.
+#
+# TASK_MSG
+# String prepended to all normal message written to
+# standard output.
+#
+
+__task_users__="yes"
+__task_users_init__="_task_users_init"
+
+task_load cleanup
+task_load echo
+task_load quote
+task_load refcount
+task_load truthy
+task_load usergroup
+task_load usergroup_exists
+
+task_users()
+{
+ : ${PKGNAME:=${0##*/}}
+ : ${PKG_CREATE_USERGROUP:=yes}
+ : ${TASK_MSG:=""}
+
+ local arg
+ local echo="task_echo"
+ local OPTIND=1
+ while getopts ":s" arg "$@"; do
+ case $arg in
+ s) echo=":" ;;
+ *) return 127 ;;
+ esac
+ done
+ shift $(( ${OPTIND} - 1 ))
+ [ $# -gt 0 ] || return 127
+
+ local action="$1"; shift
+ case $action in
+ add|remove|check-add|check-remove)
+ : "valid action" ;;
+ *) return 0 ;;
+ esac
+
+ local create="yes"
+ task_is_truthy "${PKG_CREATE_USERGROUP}" || create=
+
+ local result line_result
+ local save_IFS user group uid descr home shell msg
+
+ result=0
+ local hash tag entry
+ while read hash tag entry; do
+ # Filter for "# USER:".
+ case $hash/$tag in
+ "#/USER:")
+ : "use this line" ;;
+ *) continue ;;
+ esac
+
+ save_IFS=$IFS; IFS=:
+ set -o noglob; set -- $entry; set +o noglob
+ user=$1; group=$2 # required
+ uid=$3; descr=$4; home=$5; shell=$6
+ IFS=$save_IFS
+ [ -n "$user" -a -n "$group" ] || continue
+
+ if [ -n "$uid" ]; then
+ msg="$user (uid = $uid)"
+ else
+ msg="$user"
+ fi
+ msg="$msg: $group"
+ [ -z "$home" ] || msg="$msg, $home"
+ [ -z "$shell" ] || msg="$msg, $shell"
+
+ line_result=0
+ case $action in
+ add) if task_refcount add users "$user"; then
+ task_user_exists "$user" "$uid"
+ case $? in
+ 0) # $user exists and has uid $uid
+ $echo "${TASK_MSG}! user already exists: $msg" ;;
+ 1) # neither $user nor $uid exist
+ if [ -z "$create" ]; then
+ $echo "${TASK_MSG}! user creation skipped: $msg"
+ elif task_adduser "$user" "$group" "$uid" "$descr" "$home" "$shell"; then
+ $echo "${TASK_MSG}> user created: $msg"
+ task_quote "$user"
+ __task_users_error__="$__task_users_error__ $_quoted"
+ else
+ $echo "${TASK_MSG}! user not created: $msg"
+ line_result=1
+ fi ;;
+ 2) $echo "${TASK_MSG}! user conflict: $msg"
+ result=1
+ break ;;
+ *) $echo "${TASK_MSG}! user not created: $msg"
+ line_result=1 ;;
+ esac
+ else
+ # add refcount failed; skip to next line
+ $echo "${TASK_MSG}! refcount add failure: users $msg"
+ result=1
+ continue
+ fi ;;
+ remove) if task_refcount remove users "$user"; then
+ if task_refcount exists users "$user"; then
+ : "refcount is not zero"
+ else
+ # delete the reference count
+ task_refcount delete users "$user"
+ fi
+ else
+ # remove refcount failed
+ $echo "${TASK_MSG}! refcount remove failure: users $msg"
+ line_result=1
+ fi ;;
+ check-add)
+ if task_user_exists "$user" "$uid"; then
+ : "user already exists"
+ else
+ task_echo "!!! INFO: ${PKGNAME}: Create user: $msg"
+ line_result=1
+ fi ;;
+ check-remove)
+ if task_user_exists "$user" "$uid"; then
+ task_echo "!!! INFO: ${PKGNAME}: Remove user if unused: $user"
+ line_result=1
+ fi ;;
+ esac
+ [ $line_result -eq 0 ] || result=1
+ done
+
+ # Clear users to remove in case of error if all users added
+ # successfully.
+ #
+ [ $result -gt 0 ] || __task_users_error__=
+
+ return $result
+}
+
+_task_users_cleanup()
+{
+ eval set -- $__task_users_error__
+ local user
+ for user; do
+ if task_user_exists "$user"; then
+ task_echo "!!! ERROR: ${PKGNAME}: User created before error: $user"
+ fi
+ done
+ __task_users_error__=
+}
+
+_task_users_init()
+{
+ task_cleanup_add_hook _task_users_cleanup
+}
+
+# Static variable for users that should be removed if an error occurs.
+__task_users_error__=