summaryrefslogtreecommitdiff
path: root/mk/pkgtasks
diff options
context:
space:
mode:
authorjlam <jlam@pkgsrc.org>2017-06-01 02:06:04 +0000
committerjlam <jlam@pkgsrc.org>2017-06-01 02:06:04 +0000
commit097f66db251a632208d70b1e836294373236b6a5 (patch)
tree8163edb98fb66c45fbe4e8d36ae5d7950660c3e4 /mk/pkgtasks
parent90ec6bcdd0556552a73fb825631d794bc5bef991 (diff)
downloadpkgsrc-097f66db251a632208d70b1e836294373236b6a5.tar.gz
Add "pkgtasks" framework to generate data files used by pkgtasks.
A full dependency on the "pkgtasks" package will be added if a non-empty data file is generated by the framework. This framework is not yet hooked into bsd.pkg.mk, pending some other changes.
Diffstat (limited to 'mk/pkgtasks')
-rw-r--r--mk/pkgtasks/bsd.pkgtasks.mk190
-rw-r--r--mk/pkgtasks/directories.mk164
-rw-r--r--mk/pkgtasks/files.mk235
-rw-r--r--mk/pkgtasks/fonts.mk108
-rw-r--r--mk/pkgtasks/info_files.mk79
-rw-r--r--mk/pkgtasks/ocaml_findlib.mk84
-rw-r--r--mk/pkgtasks/permissions.mk112
-rw-r--r--mk/pkgtasks/shells.mk72
-rw-r--r--mk/pkgtasks/shlibs.mk60
-rw-r--r--mk/pkgtasks/tests/Kyuafile61
-rwxr-xr-xmk/pkgtasks/tests/create_usergroup_test169
-rwxr-xr-xmk/pkgtasks/tests/directories_test111
-rwxr-xr-xmk/pkgtasks/tests/files_test168
-rwxr-xr-xmk/pkgtasks/tests/fonts_test116
-rwxr-xr-xmk/pkgtasks/tests/groups_test113
-rwxr-xr-xmk/pkgtasks/tests/info_files_test109
-rwxr-xr-xmk/pkgtasks/tests/ocaml_findlib_test104
-rwxr-xr-xmk/pkgtasks/tests/permissions_test110
-rwxr-xr-xmk/pkgtasks/tests/pkgtasks_test139
-rwxr-xr-xmk/pkgtasks/tests/shells_test104
-rwxr-xr-xmk/pkgtasks/tests/shlibs_test100
-rw-r--r--mk/pkgtasks/tests/test.mk69
-rwxr-xr-xmk/pkgtasks/tests/users_test113
-rw-r--r--mk/pkgtasks/usergroup.mk275
-rw-r--r--mk/pkgtasks/usergroup.sh83
25 files changed, 3048 insertions, 0 deletions
diff --git a/mk/pkgtasks/bsd.pkgtasks.mk b/mk/pkgtasks/bsd.pkgtasks.mk
new file mode 100644
index 00000000000..23a2d259771
--- /dev/null
+++ b/mk/pkgtasks/bsd.pkgtasks.mk
@@ -0,0 +1,190 @@
+# $NetBSD: bsd.pkgtasks.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+_VARGROUPS+= pkgtasks
+
+# PKG_CONFIG
+# User-settable variable for whether the directory- and
+# file-handling should be performed automatically, or if the
+# user should be warned instead.
+#
+# Possible: yes, no (case-insensitive)
+# Default: yes
+#
+# PKG_CONFIG_PERMS
+# User-settable variable for whether to set permissions and
+# ownership on files and directories, or if the user should be
+# warned instead.
+#
+# Possible: yes, no (case-insensitive)
+# Default: yes
+#
+# PKG_CREATE_USERGROUP
+# User-settable variable for whether groups and users should be
+# added automatically, or if the user should be warned instead.
+#
+# Possible: yes, no (case-insensitive)
+# Default: yes
+#
+# PKG_INIT_SCRIPTS
+# User-settable variable for whether to copy init scripts into
+# the appropriate places for the init system to locate them,
+# e.g., copy rc.d scripts to ${RCD_SCRIPTS_DIR}, or if the user
+# should be warned instead.
+#
+# Possible: yes, no (case-insensitive)
+# Default: yes
+#
+# PKG_REGISTER_SHELLS
+# User-settable variable for whether to register shells in the
+# login shell database (/etc/shells) automatically, or if the
+# user should be warned instead.
+#
+# Possible: yes, no (case-insensitive)
+# Default: yes
+#
+# PKG_UPDATE_FONTS_DB
+# User-settable variable for whether to update the databases in
+# fonts directories automatically, or if the user should be
+# warned instead.
+#
+# Possible: yes, no (case-insensitive)
+# Default: yes
+#
+_USER_VARS.pkgtasks+= PKG_CONFIG PKG_CONFIG_PERMS PKG_INIT_SCRIPTS
+PKG_CONFIG?= yes
+PKG_CONFIG_PERMS?= no
+PKG_CREATE_USERGROUP?= yes
+PKG_INIT_SCRIPTS?= ${PKG_RCD_SCRIPTS:Uno} # deprecated
+PKG_REGISTER_SHELLS?= yes
+PKG_UPDATE_FONTS_DB?= yes
+FILES_SUBST+= PKG_CONFIG=${PKG_CONFIG:tl:Q}
+FILES_SUBST+= PKG_CONFIG_PERMS=${PKG_CONFIG_PERMS:tl:Q}
+FILES_SUBST+= PKG_CREATE_USERGROUP=${PKG_CREATE_USERGROUP:tl:Q}
+FILES_SUBST+= PKG_INIT_SCRIPTS=${PKG_INIT_SCRIPTS:tl:Q}
+FILES_SUBST+= PKG_REGISTER_SHELLS=${PKG_REGISTER_SHELLS:tl:Q}
+FILES_SUBST+= PKG_UPDATE_FONTS_DB=${PKG_UPDATE_FONTS_DB:tl:Q}
+
+# FILES_SUBST
+# Package-settable varibable that lists "variable=value" pairs
+# that is turned into a sed(1) script for substituting
+# "@variable@" with "value".
+#
+# FILES_SUBST_SED
+# System variable set by this file that is list of
+# "variable=value" pairs in ${FILES_SUBST} turned into a sed(1)
+# script for substituting "@variable@" with "value".
+#
+_PKG_VARS.pkgtasks+= FILES_SUBST
+_SYS_VARS.pkgtasks+= FILES_SUBST_SED
+FILES_SUBST_SED= ${FILES_SUBST:S/=/@!/:S/$/!g/:S/^/ -e s!@/}
+
+# PKG_REFCOUNT_DBDIR
+# The location of the reference-count database directory used
+# by installed packages.
+#
+# Possible: any valid directory path
+# Default: ${PKG_DBDIR}.refcount
+#
+PKG_REFCOUNT_DBDIR?= ${PKG_DBDIR}.refcount
+FILES_SUBST+= PKG_PREFIX=${PREFIX:Q}
+FILES_SUBST+= PKG_REFCOUNT_DBDIR=${PKG_REFCOUNT_DBDIR:Q}
+
+# Directory to hold the built objects.
+_PKGTASKS_DIR= ${WRKDIR}/.pkgtasks
+
+# List of generated task data files.
+_PKGTASKS_DATAFILES= # empty
+
+# USE_PKGTASKS
+# Public variable set by this file that indicates whether
+# package tasks are needed.
+#
+# Possible: yes, no
+#
+_SYS_VARS.pkgtasks= USE_PKGTASKS
+USE_PKGTASKS= no
+
+.include "${PKGSRCDIR}/mk/pkgtasks/directories.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/files.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/fonts.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/info_files.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/ocaml_findlib.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/permissions.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/shells.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/shlibs.mk"
+.include "${PKGSRCDIR}/mk/pkgtasks/usergroup.mk"
+
+# Add a dependency on pkgtasks if package tasks are needed.
+.if "${USE_PKGTASKS:tl}" == "yes"
+DEPENDS+= pkgtasks-1>=1.9:../../pkgtools/pkgtasks
+.endif
+TASK_MODULE_DIR?= ${LOCALBASE}/share/pkgtasks-1
+
+# PKGTASKS_DATAFILE
+# The formatted data file for use by pkgtools/pkgtasks.
+#
+_SYS_VARS.pkgtasks= PKGTASKS_DATAFILE
+PKGTASKS_DATAFILE= ${_PKGTASKS_DIR}/pkgtasks-datafile
+
+${PKGTASKS_DATAFILE}: ${_PKGTASKS_DATAFILES}
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}${CAT} ${.ALLSRC} > ${.TARGET:Q}.tmp
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
+
+.PHONY: pkgtasks
+pkgtasks: ${PKGTASKS_DATAFILE}
+
+# Variables for programs used by pkgtasks.
+FILES_SUBST+= AWK=${AWK:Q}
+FILES_SUBST+= CAT=${CAT:Q}
+FILES_SUBST+= CHMOD=${CHMOD:Q}
+FILES_SUBST+= CHOWN=${CHOWN:Q}
+FILES_SUBST+= CP=${CP:Q}
+FILES_SUBST+= DATE=${DATE:Q}
+FILES_SUBST+= FIND=${FIND:Q}
+FILES_SUBST+= ID=${ID:Q}
+FILES_SUBST+= LDCONFIG=${LDCONFIG:Q}
+FILES_SUBST+= LN=${LN:Q}
+FILES_SUBST+= LS=${LS:Q}
+FILES_SUBST+= MKDIR=${MKDIR:Q}
+FILES_SUBST+= MKTEMP=${MKTEMP:Q}
+FILES_SUBST+= MV=${MV:Q}
+FILES_SUBST+= PRINTF=${PRINTF:Q}
+FILES_SUBST+= RM=${RM:Q}
+FILES_SUBST+= RMDIR=${RMDIR:Q}
+FILES_SUBST+= SED=${SED:Q}
+FILES_SUBST+= SORT=${SORT:Q}
+FILES_SUBST+= UNAME=${UNAME:Q}
+
+# Variables for addgroup/adduser programs used by pkgtasks.
+FILES_SUBST+= GROUPADD=${GROUPADD:Q}
+FILES_SUBST+= PW=${PW:Q} # DragonFly, FreeBSD
+FILES_SUBST+= PWD_MKDB=${PWD_MKDB:Q} # MirBSD
+FILES_SUBST+= USERADD=${USERADD:Q}
diff --git a/mk/pkgtasks/directories.mk b/mk/pkgtasks/directories.mk
new file mode 100644
index 00000000000..314dfcdc37b
--- /dev/null
+++ b/mk/pkgtasks/directories.mk
@@ -0,0 +1,164 @@
+# $NetBSD: directories.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the directories package task.
+
+# MAKE_DIRS
+# OWN_DIRS
+# REQD_DIRS
+# List of directories that should be created and destroyed when
+# the package is installed and removed.
+#
+# OWN_DIRS is for directories owned by the package and the user
+# is prompted to remove the directory if it isn't empty. The
+# directories are created or removed only if PKG_CONFIG is "yes".
+#
+# MAKE_DIRS is for directories used by the package and the user
+# is never prompted to remove non-empty directories. The
+# directories are created or removed only if PKG_CONFIG is "yes".
+#
+# REQD_DIRS is for directories used by the package that must
+# always be created (PKG_CONFIG is ignored), and the user is
+# never prompted to remove non-empty directories. All
+# directories listed in REQD_DIRS should be under ${PREFIX}.
+# The use-case for REQD_DIRS is very specialized, and most
+# packages should be using either OWN_DIRS or MAKE_DIRS instead.
+#
+# If the directory pathname is a relative path, then it is taken
+# to be relative to ${PREFIX}.
+#
+# MAKE_DIRS_PERMS
+# OWN_DIRS_PERMS
+# REQD_DIRS_PERMS
+# List of sublists representing directories with ownership and
+# explicit modes that should be created and destroyed when the
+# package is installed and removed. The sublists are of the
+# form:
+#
+# <directory> <owner> <group> <mode>
+#
+# These variables have the same usage as the similarly-named
+# variables that don't end in "_PERMS".
+#
+_PKG_VARS.pkgtasks+= MAKE_DIRS MAKE_DIRS_PERMS \
+ OWN_DIRS OWN_DIRS_PERMS \
+ REQD_DIRS REQD_DIRS_PERMS
+MAKE_DIRS?= # empty
+MAKE_DIRS_PERMS?= # empty
+OWN_DIRS?= # empty
+OWN_DIRS_PERMS?= # empty
+REQD_DIRS?= # empty
+REQD_DIRS_PERMS?= # empty
+
+# Trigger pkgtasks dependency if needed.
+_PKGTASKS_DATAVARS.directories= \
+ MAKE_DIRS MAKE_DIRS_PERMS \
+ OWN_DIRS OWN_DIRS_PERMS \
+ REQD_DIRS REQD_DIRS_PERMS
+.for _var_ in ${_PKGTASKS_DATAVARS.directories}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+.endfor
+
+# Strip leading "${PREFIX}/" from the directory pathnames.
+_MAKE_DIRS= ${MAKE_DIRS:S|^${PREFIX}/||g}
+_MAKE_DIRS_PERMS= ${MAKE_DIRS_PERMS:S|^${PREFIX}/||g}
+_OWN_DIRS= ${OWN_DIRS:S|^${PREFIX}/||g}
+_OWN_DIRS_PERMS= ${OWN_DIRS_PERMS:S|^${PREFIX}/||g}
+_REQD_DIRS= ${REQD_DIRS:S|^${PREFIX}/||g}
+_REQD_DIRS_PERMS= ${REQD_DIRS_PERMS:S|^${PREFIX}/||g}
+
+# Assert that the variables have the right number of words and
+# that no directory is listed in more than one variable.
+#
+_ALL_DIRS.directories= # empty
+.for _var_ in MAKE_DIRS OWN_DIRS REQD_DIRS
+. for d in ${${_var_}}
+_DIRS.${d}+= ${_var_}
+_ALL_DIRS.directories+= ${d}
+. endfor
+.endfor
+.for _var_ in MAKE_DIRS_PERMS OWN_DIRS_PERMS REQD_DIRS_PERMS
+. if empty(${_var_}) || empty(${_var_}:C/.*/4/:M*:S/4 4 4 4//gW)
+# ${_var_} has a multiple of 4 words.
+. for d o g m in ${${_var_}}
+_DIRS.${d}+= ${_var_}
+_ALL_DIRS.directories+= ${d}
+. endfor
+. else
+PKG_FAIL_REASON+= ${_var_:Q}" must have a multiple of 4 words."
+. endif
+.endfor
+.for d in ${_ALL_DIRS.directories:O:u}
+. if ${_DIRS.${d}:[#]} != 1
+PKG_FAIL_REASON+= ${d:Q}" is listed more than once: "${_DIRS.${d}:Q}
+. endif
+.endfor
+
+_PKGTASKS_DATA.directories= ${_PKGTASKS_DIR}/directories
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.directories}
+
+${_PKGTASKS_DATA.directories}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET:Q}.tmp
+ ${RUN}set -- args ${_MAKE_DIRS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ dir="$$1"; shift; \
+ ${ECHO} "# DIR: $$dir m" >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_MAKE_DIRS_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ dir="$$1"; owner="$$2"; group="$$3"; mode="$$4"; shift 4; \
+ ${ECHO} "# DIR: $$dir m $$mode $$owner $$group" \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_OWN_DIRS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ dir="$$1"; shift; \
+ ${ECHO} "# DIR: $$dir mo" >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_OWN_DIRS_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ dir="$$1"; owner="$$2"; group="$$3"; mode="$$4"; shift 4; \
+ ${ECHO} "# DIR: $$dir mo $$mode $$owner $$group" \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_REQD_DIRS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ dir="$$1"; shift; \
+ ${ECHO} "# DIR: $$dir fm" >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_REQD_DIRS_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ dir="$$1"; owner="$$2"; group="$$3"; mode="$$4"; shift 4; \
+ ${ECHO} "# DIR: $$dir fm $$mode $$owner $$group" \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/files.mk b/mk/pkgtasks/files.mk
new file mode 100644
index 00000000000..8f13d4f5d22
--- /dev/null
+++ b/mk/pkgtasks/files.mk
@@ -0,0 +1,235 @@
+# $NetBSD: files.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the files package task.
+
+###
+# CONF_FILES
+# REQD_FILES
+# _INIT_SCRIPTS
+# List of pairs of files that should be copied and removed when
+# the package is installed and removed. The pairs are of the
+# form:
+#
+# <source> <target>
+#
+# During installation, if the target file does not exist, then the
+# source file is copied into place. During removal, if the target
+# file does not differ from the source file, then the target file
+# is also removed.
+#
+# CONF_FILES triggers system changes only if PKG_CONFIG is "yes".
+# REQD_FILES always trigger system changes (PKG_CONFIG is ignored).
+# _INIT_SCRIPTS trigger system changes only if PKG_CONFIG and
+# PKG_INIT_SCRIPTS are both "yes".
+#
+# The use-case for REQD_FILES is very specialized, and most packages
+# should be using CONF_FILES instead.
+#
+# If the source and target pathnames are relative paths, then they
+# are taken to be relative to ${PREFIX}.
+#
+# CONF_FILES_MODE
+# REQD_FILES_MODE
+# _INIT_SCRIPTS_MODE
+# These are the file modes for the target files listed in CONF_FILES,
+# REQD_FILES, and _INIT_SCRIPTS, respectively.
+#
+# CONF_FILES_PERMS
+# REQD_FILES_PERMS
+# _INIT_SCRIPTS_PERMS
+# List of sublists representing files with ownership and explicit
+# modes that should be copied and removed when the package is
+# installed and removed. The sublists are of the form:
+#
+# <source> <target> <owner> <group> <mode>
+#
+# These variables have the same usage as the similarly-named
+# variables that don't end in "_PERMS".
+#
+# The _INIT_SCRIPTS* variables are a hook for bsd.init.mk into the config
+# file framework. They should not be used by packages.
+#
+_PKG_VARS.pkgtasks+= CONF_FILES CONF_FILES_MODE CONF_FILES_PERMS \
+ REQD_FILES REQD_FILES_MODE REQD_FILES_PERMS
+CONF_FILES?= # empty
+CONF_FILES_MODE?= 0644
+CONF_FILES_PERMS?= # empty
+REQD_FILES?= # empty
+REQD_FILES_MODE?= 0644
+REQD_FILES_PERMS?= # empty
+_INIT_SCRIPTS?= # empty
+_INIT_SCRIPTS_MODE?= 0755
+_INIT_SCRIPTS_PERMS?= # empty
+
+# Trigger pkgtasks dependency if needed.
+_PKGTASKS_DATAVARS.files+= \
+ CONF_FILES CONF_FILES_PERMS \
+ REQD_FILES REQD_FILES_PERMS \
+ _INIT_SCRIPTS _INIT_SCRIPTS_PERMS
+.for _var_ in ${_PKGTASKS_DATAVARS.files}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+.endfor
+
+# Strip leading "${PREFIX}/" from the file pathnames.
+_CONF_FILES= ${CONF_FILES:S|^${PREFIX}/||g}
+_CONF_FILES_PERMS= ${CONF_FILES_PERMS:S|^${PREFIX}/||g}
+_REQD_FILES= ${REQD_FILES:S|^${PREFIX}/||g}
+_REQD_FILES_PERMS= ${REQD_FILES_PERMS:S|^${PREFIX}/||g}
+__INIT_SCRIPTS= ${_INIT_SCRIPTS:S|^${PREFIX}/||g}
+__INIT_SCRIPTS_PERMS= ${_INIT_SCRIPTS_PERMS:S|^${PREFIX}/||g}
+
+# Assert that the variables have the right number of words and
+# that no target file is listed in more than one variable.
+#
+_ALL_FILES.files= # empty
+.if !empty(_VALID.files)
+. for _var_ in CONF_FILES REQD_FILES _INIT_SCRIPTS
+. if empty(${_var_}) || empty(${_var_}:C/.*/2/:M*:S/2 2//gW)
+# ${_var_} has a multiple of 2 words.
+. for s t in ${${_var_}}
+_FILES.${t}+= ${_var_}
+_ALL_FILES.files+= ${t}
+. endfor
+. else
+PKG_FAIL_REASON+= ${_var_:Q}" must have a multiple of 2 words."
+. endif
+. endfor
+. for _var_ in CONF_FILES_PERMS REQD_FILES_PERMS _INIT_SCRIPT_PERMS
+. if empty(${_var_}) || empty(${_var_}:C/.*/5/:M*:S/5 5 5 5 5//gW)
+# ${_var_} has a multiple of 5 words.
+. for s t o g m in ${${_var_}}
+_FILES.${t}+= ${_var_}
+_ALL_FILES.files+= ${t}
+. endfor
+. else
+PKG_FAIL_REASON+= ${_var_:Q}" must have a multiple of 5 words."
+. endif
+. endfor
+.endif
+.for t in ${_ALL_FILES.files:O:u}
+. if ${_FILES.${t}:[#]} != 1
+PKG_FAIL_REASON+= ${t:Q}" is listed more than once: "${_FILES.${t}:Q}
+. endif
+.endfor
+
+_PKGTASKS_DATA.files= ${_PKGTASKS_DIR}/files
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.files}
+
+${_PKGTASKS_DATA.files}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET:Q}.tmp
+ ${RUN}set -- args ${_CONF_FILES}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ egfile="$$1"; file="$$2"; shift 2; \
+ ${ECHO} "# FILE: $$file c $$egfile "${CONF_FILES_MODE:Q} \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_CONF_FILES_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ egfile="$$1"; file="$$2"; \
+ owner="$$3"; group="$$4"; mode="$$5"; shift 5; \
+ ${ECHO} "# FILE: $$file c $$egfile $$mode $$owner $$group" \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_REQD_FILES}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ egfile="$$1"; file="$$2"; shift 2; \
+ ${ECHO} "# FILE: $$file cf $$egfile "${REQD_FILES_MODE:Q} \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${_REQD_FILES_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ egfile="$$1"; file="$$2"; \
+ owner="$$3"; group="$$4"; mode="$$5"; shift 5; \
+ ${ECHO} "# FILE: $$file cf $$egfile $$mode $$owner $$group" \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${__INIT_SCRIPTS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ egfile="$$1"; file="$$2"; shift 2; \
+ ${ECHO} "# FILE: $$file cr $$egfile "${_INIT_SCRIPTS_MODE:Q} \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}set -- args ${__INIT_SCRIPTS_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ egfile="$$1"; file="$$2"; \
+ owner="$$3"; group="$$4"; mode="$$5"; shift 5; \
+ ${ECHO} "# FILE: $$file cr $$egfile $$mode $$owner $$group" \
+ >> ${.TARGET:Q}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
+
+privileged-install-hook: _pkgtasks-files-postinstall-check
+
+_pkgtasks-files-postinstall-check: .PHONY
+ ${RUN}set -- args ${_CONF_FILES}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ ${TEST} "$$#" -gt 2 || break; \
+ egfile=${DESTDIR:Q}${PREFIX:Q}"/$$1"; shift 2; \
+ ${TEST} -f "$$egfile" || ${TEST} -c "$$egfile" || \
+ ${FAIL_MSG} "CONF_FILES $$egfile does not exist."; \
+ done
+ ${RUN}set -- args ${_CONF_FILES_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ ${TEST} "$$#" -gt 5 || break; \
+ egfile=${DESTDIR:Q}${PREFIX:Q}"/$$1"; shift 5; \
+ ${TEST} -f "$$egfile" || ${TEST} -c "$$egfile" || \
+ ${FAIL_MSG} "CONF_FILES_PERMS $$egfile does not exist.";\
+ done
+ ${RUN}set -- args ${_REQD_FILES}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ ${TEST} "$$#" -gt 2 || break; \
+ egfile=${DESTDIR:Q}${PREFIX:Q}"/$$1"; shift 2; \
+ ${TEST} -f "$$egfile" || ${TEST} -c "$$egfile" || \
+ ${FAIL_MSG} "REQD_FILES $$egfile does not exist."; \
+ done
+ ${RUN}set -- args ${_REQD_FILES_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ ${TEST} "$$#" -gt 5 || break; \
+ egfile=${DESTDIR:Q}${PREFIX:Q}"/$$1"; shift 5; \
+ ${TEST} -f "$$egfile" || ${TEST} -c "$$egfile" || \
+ ${FAIL_MSG} "REQD_FILES_PERMS $$egfile does not exist.";\
+ done
+ ${RUN}set -- args ${__INIT_SCRIPTS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ ${TEST} "$$#" -gt 2 || break; \
+ egfile=${DESTDIR:Q}${PREFIX:Q}"/$$1"; shift 2; \
+ ${TEST} -f "$$egfile" || ${TEST} -c "$$egfile" || \
+ ${FAIL_MSG} "REQD_FILES $$egfile does not exist."; \
+ done
+ ${RUN}set -- args ${__INIT_SCRIPTS_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ ${TEST} "$$#" -gt 5 || break; \
+ egfile=${DESTDIR:Q}${PREFIX:Q}"/$$1"; shift 5; \
+ ${TEST} -f "$$egfile" || ${TEST} -c "$$egfile" || \
+ ${FAIL_MSG} "REQD_FILES_PERMS $$egfile does not exist.";\
+ done
diff --git a/mk/pkgtasks/fonts.mk b/mk/pkgtasks/fonts.mk
new file mode 100644
index 00000000000..c842c54a84e
--- /dev/null
+++ b/mk/pkgtasks/fonts.mk
@@ -0,0 +1,108 @@
+# $NetBSD: fonts.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the fonts package task.
+
+# PKG_UPDATE_FONTS_DB
+# Whether to automatically update the fonts databases.
+#
+# Possible: yes, no
+# Default: yes
+#
+_USER_VARS.pkgtasks+= PKG_UPDATE_FONTS_DB
+PKG_UPDATE_FONTS_DB?= yes
+FILES_SUBST+= PKG_UPDATE_FONTS_DB=${PKG_UPDATE_FONTS_DB:Q}
+
+# FONTS_DIRS.<type>
+# List of directories in which the font databases are updated.
+# The supported font types are:
+#
+# ttf TrueType fonts
+# type1 Type1 fonts
+# x11 X fonts, e.g., PCF, SNF, BDF, etc.
+#
+_PKG_VARS.pkgtasks+= FONTS_DIRS.ttf FONTS.DIRS.type1 FONTS_DIRS.x11
+FONTS_DIRS.ttf?= # empty
+FONTS_DIRS.type1?= # empty
+FONTS_DIRS.x11?= # empty
+
+# Trigger pkgtasks dependency if needed.
+_PKGTASKS_DATAVARS.fonts= FONTS_DIRS.ttf FONTS.DIRS.type1 FONTS_DIRS.x11
+.for _var_ in ${_PKGTASKS_DATAVARS.fonts}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+.endfor
+
+_FONTS_DIRS.x11= # empty
+.if !empty(FONTS_DIRS.ttf:M*)
+. if ${X11_TYPE} == "modular"
+USE_TOOLS+= mkfontscale:run
+FILES_SUBST+= MKFONTSCALE=${TOOLS_PATH.mkfontscale:Q}
+. else
+USE_TOOLS+= ttmkfdir:run
+FILES_SUBST+= TTMKFDIR=${TOOLS_PATH.ttmkfdir:Q}
+. endif
+_FONTS_DIRS.x11+= ${FONTS_DIRS.ttf}
+.endif
+.if !empty(FONTS_DIRS.type1:M*)
+. if ${X11_TYPE} == "modular"
+USE_TOOLS+= mkfontscale:run
+FILES_SUBST+= MKFONTSCALE=${TOOLS_PATH.mkfontscale:Q}
+. else
+USE_TOOLS+= type1inst:run
+FILES_SUBST+= TTMKFDIR=${TOOLS_PATH.type1inst:Q}
+. endif
+_FONTS_DIRS.x11+= ${FONTS_DIRS.type1}
+.endif
+_FONTS_DIRS.x11+= ${FONTS_DIRS.x11}
+.if !empty(_FONTS_DIRS.x11:M*)
+USE_TOOLS+= mkfontdir:run
+FILES_SUBST+= MKFONTDIR=${TOOLS_PATH:mkfontdir:Q}
+. if ${X11_TYPE} == "modular"
+DEPENDS+= encodings-[0-9]*:../../fonts/encodings
+X11_ENCODINGSDIR?= ${X11BASE}/share/fonts/X11/encodings
+. else
+X11_ENCODINGSDIR?= ${X11BASE}/lib/fonts/X11/encodings
+. endif
+FILES_SUBST+= X11_ENCODINGSDIR=${X11_ENCODINGSDIR:Q}
+.endif
+
+_PKGTASKS_DATA.fonts= ${_PKGTASKS_DIR}/fonts
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.fonts}
+
+${_PKGTASKS_DATA.fonts}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+.for _fonttype_ in ttf type1 x11
+. for _fontdir_ in ${FONTS_DIRS.${_fonttype_}:S|^${PREFIX}/||g}
+ ${RUN}${ECHO} "# FONTS: "${_fontdir_:Q} ${_fonttype_:Q} >> ${.TARGET}.tmp
+. endfor
+.endfor
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/info_files.mk b/mk/pkgtasks/info_files.mk
new file mode 100644
index 00000000000..7c6edab6ac2
--- /dev/null
+++ b/mk/pkgtasks/info_files.mk
@@ -0,0 +1,79 @@
+# $NetBSD: info_files.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the info_files package task.
+
+# INFO_DIR
+# The location of the directory containing the "dir" index file
+# to be updated. If the location is a relative path, then it
+# is taken to be relative to ${PREFIX}.
+#
+# Possible: any path
+# Default: (empty)
+#
+_PKG_VARS.pkgtasks+= INFO_DIR
+INFO_DIR?= # empty
+
+# Strip leading "${PREFIX}/" from the directory pathname.
+_INFO_DIR= ${INFO_DIR:S|^${PREFIX}/||g}
+
+# INFO_FILES
+# Whether the package has GNU info files that need to trigger an
+# update of the "dir" index files.
+#
+# Possible: set, or unset
+# Default: unset
+#
+_PKG_VARS.pkgtasks+= INFO_FILES
+
+.if defined(INFO_FILES)
+USE_TOOLS+= install-info:run
+FILES_SUBST+= INSTALL_INFO=${INSTALL_INFO:Q}
+USE_PKGTASKS= yes # trigger pkgtasks dependency if needed
+.endif
+
+_PKGTASKS_DATA.info_files= ${_PKGTASKS_DIR}/info_files
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.info_files}
+
+# ${INFO_FILES_cmd} is defined by the plist module.
+${_PKGTASKS_DATA.info_files}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+.if defined(INFO_FILES)
+ ${RUN}${INFO_FILES_cmd} | \
+ while IFS= read file; do \
+ infodir=${_INFO_DIR:Q}; \
+ case $$infodir in \
+ "") ${ECHO} "# INFO: $$file" ;; \
+ *) ${ECHO} "# INFO: $$file $$infodir" ;; \
+ esac; \
+ done > ${.TARGET:Q}.tmp
+.else
+ ${RUN}exec > ${.TARGET:Q}.tmp
+.endif
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/ocaml_findlib.mk b/mk/pkgtasks/ocaml_findlib.mk
new file mode 100644
index 00000000000..3713df3253f
--- /dev/null
+++ b/mk/pkgtasks/ocaml_findlib.mk
@@ -0,0 +1,84 @@
+# $NetBSD: ocaml_findlib.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the ocaml_findlib package task.
+
+# OCAML_FINDLIB_REGISTER
+# Package-settable variable for whether to automatically update
+# the OCaml findlib ld.conf file.
+#
+# Possible: yes, no
+# Default: yes
+#
+_PKG_VARS.pkgtasks+= OCAML_FINDLIB_REGISTER
+OCAML_FINDLIB_REGISTER?= yes
+
+# OCAML_FINDLIB_DIRS
+# List of directories relative to ${OCAML_SITELIBDIR} that should
+# be added or removed from the findlib ld.conf file.
+#
+# OCAML_SITELIBDIR
+# Path relative to ${PREFIX} that contains the installed OCaml
+# packages. This variable is set by ocaml.mk.
+#
+# Default: lib/ocaml/site-lib
+#
+_PKG_VARS.pkgtasks+= OCAML_FINDLIB_DIRS
+_SYS_VARS.pkgtasks+= OCAML_SITELIBDIR
+OCAML_FINDLIB_DIRS?= # empty
+OCAML_SITELIBDIR?= lib/ocaml/site-lib
+FILES_SUBST+= OCAML_SITELIB=${OCAML_SITELIBDIR:Q}
+
+# Trigger pkgtasks dependency if needed.
+.if "${OCAML_FINDLIB_REGISTER:tl}" == "yes"
+_PKGTASKS_DATAVARS.ocaml_findlib= OCAML_FINDLIB_DIRS
+. for _var_ in ${_PKGTASKS_DATAVARS.ocaml_findlib}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+. endfor
+.endif
+
+# Strip leading "${PREFIX}/" from directory pathnames.
+_OCAML_FINDLIB_DIRS= ${OCAML_FINDLIB_DIRS:S|^${PREFIX}/${OCAML_SITELIBDIR}/||g}
+
+_PKGTASKS_DATA.ocaml_findlib= ${_PKGTASKS_DIR}/ocaml_findlib
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.ocaml_findlib}
+
+# Only emit FINDLIB data lines if ${OCAML_FINDLIB_REGISTER} is "yes.
+${_PKGTASKS_DATA.ocaml_findlib}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+ ${RUN}${TEST} "${OCAML_FINDLIB_REGISTER:tl}" = "yes" || exit 0; \
+ set -- args ${_OCAML_FINDLIB_DIRS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ libdir="$$1"; shift; \
+ ${ECHO} "# FINDLIB: $$libdir" >> ${.TARGET}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/permissions.mk b/mk/pkgtasks/permissions.mk
new file mode 100644
index 00000000000..baa4db984fc
--- /dev/null
+++ b/mk/pkgtasks/permissions.mk
@@ -0,0 +1,112 @@
+# $NetBSD: permissions.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the permissions package task.
+
+# SPECIAL_PERMS
+# List of blocks of four words of the following form:
+#
+# <file> <owner> <group> <mode>
+#
+# The <file> (it may be a directory) is changed to be owned by
+# <owner>:<group> with <mode> permissions. If <file> is a
+# relative path, then it is taken to be relative to ${PREFIX}.
+#
+# SPECIAL_PERMS should be used primarily to change permissions of
+# files or directories listed in the PLIST. This may be used to
+# ensure certain files are set-uid or to change the ownership of a
+# directory.
+#
+_PKG_VARS.pkgtasks+= SPECIAL_PERMS
+SPECIAL_PERMS?= # empty
+
+# Trigger pkgtasks dependency if needed.
+_PKGTASKS_DATAVARS.permissions= SPECIAL_PERMS
+.for _var_ in ${_PKGTASKS_DATAVARS.permissions}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+.endfor
+
+# Strip leading "${PREFIX}/" from pathnames.
+_SPECIAL_PERMS= ${SPECIAL_PERMS:S|^${PREFIX}/||g}
+
+# SETUID_ROOT_PERMS
+# Convenience variable used to note an executable should be setuid
+# root, and should be used as follows:
+#
+# SPECIAL_PERMS+= /path/to/suidroot ${SETUID_ROOT_PERMS}
+#
+# SETGID_GAMES_PERMS
+# Convenience variable used to note an executable should be setgid
+# games, and should be used as follows:
+#
+# SPECIAL_PERMS+= /path/to/sgidgame ${SETGID_GAMES_PERMS}
+#
+# GAMEDATA_PERMS
+# GAMEDIR_PERMS
+# Convenience variables for files or directories that should be
+# accessible by executables that are setgid games. Since such
+# files or directories should normally live under ${VARBASE},
+# these definitions should be used roughly as follows:
+#
+# REQD_DIRS_PERMS+= /path/to/scoredir ${GAMEDIR_PERMS}
+# REQD_FILES_PERMS+= /dev/null /path/to/scorefile ${GAMEDATA_PERMS}
+#
+# Keywords: setuid setgid st_mode perms
+#
+_SYS_VARS.pkgtasks+= SETUID_ROOT_PERMS SETGID_GAMES_PERMS \
+ GAMEDATA_PERMS GAMEDIR_PERMS
+SETUID_ROOT_PERMS?= ${REAL_ROOT_USER} ${REAL_ROOT_GROUP} 4511
+SETGID_GAMES_PERMS?= ${GAMES_USER} ${GAMES_GROUP} ${GAMEMODE}
+GAMEDATA_PERMS?= ${GAMES_USER} ${GAMES_GROUP} ${GAMEDATAMODE}
+GAMEDIR_PERMS?= ${GAMES_USER} ${GAMES_GROUP} ${GAMEDIRMODE}
+
+# Assert that the variables have the right number of words.
+.for _var_ in SPECIAL_PERMS
+. if empty(${_var_}) || empty(${_var_}:C/.*/4/:M*:S/4 4 4 4//gW)
+# ${_var_} has a multiple of 4 words.
+. else
+PKG_FAIL_REASON+= ${_var_:Q}" must have a multiple of 4 words."
+. endif
+.endfor
+
+_PKGTASKS_DATA.permissions= ${_PKGTASKS_DIR}/permissions
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.permissions}
+
+${_PKGTASKS_DATA.permissions}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+ ${RUN}set -- args ${_SPECIAL_PERMS}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ path="$$1"; owner="$$2"; group="$$3"; mode="$$4"; shift 4; \
+ ${ECHO} "# PERMS: $$path $$mode $$owner $$group" \
+ >> ${.TARGET}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/shells.mk b/mk/pkgtasks/shells.mk
new file mode 100644
index 00000000000..2447df8caf9
--- /dev/null
+++ b/mk/pkgtasks/shells.mk
@@ -0,0 +1,72 @@
+# $NetBSD: shells.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the shells package task.
+
+# PKG_REGISTER_SHELLS
+# Whether to automatically update the /etc/shells database.
+#
+# Possible: yes, no
+# Default: yes
+#
+_USER_VARS.pkgtasks+= PKG_REGISTER_SHELLS
+PKG_REGISTER_SHELLS?= yes
+FILES_SUBST+= PKG_REGISTER_SHELLS=${PKG_REGISTER_SHELLS:Q}
+
+# PKG_SHELL
+# List of shell pathnames that should be added or removed from
+# the shell database, /etc/shells. If a pathname is a relative
+# path, then it is taken to be relative to ${PREFIX}.
+#
+_PKG_VARS.pkgtasks+= PKG_SHELL
+PKG_SHELL?= # empty
+
+# Trigger pkgtasks dependency if needed.
+_PKGTASKS_DATAVARS.shells= PKG_SHELL
+.for _var_ in ${_PKGTASKS_DATAVARS.shells}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+.endfor
+
+# Strip leading "${PREFIX}/" from shell pathname.
+_PKG_SHELL= ${PKG_SHELL:S|^${PREFIX}/||g}
+
+_PKGTASKS_DATA.shells= ${_PKGTASKS_DIR}/shells
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.shells}
+
+${_PKGTASKS_DATA.shells}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+ ${RUN}set -- args ${_PKG_SHELL}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ shell="$$1"; shift; \
+ ${ECHO} "# SHELL: $$shell" >> ${.TARGET}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/shlibs.mk b/mk/pkgtasks/shlibs.mk
new file mode 100644
index 00000000000..0add7deb411
--- /dev/null
+++ b/mk/pkgtasks/shlibs.mk
@@ -0,0 +1,60 @@
+# $NetBSD: shlibs.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the shlibs package task.
+
+# RUN_LDCONFIG
+# Whether to automatically update the library search paths cache.
+#
+# Possible: yes, no
+# Default: "yes" for a.out platforms, "no" otherwise
+#
+_USER_VARS.pkgtasks+= RUN_LDCONFIG
+RUN_LDCONFIG?= ${"${SHLIB_TYPE}" == "a.out":?yes:no}
+
+# Trigger pkgtasks dependency if needed.
+.if "${RUN_LDCONFIG:tl}" == "yes"
+USE_PKGTASKS= yes
+.endif
+
+_PKGTASKS_DATA.shlibs= ${_PKGTASKS_DIR}/shlibs
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.shlibs}
+
+# Directories to add to the library search path cache.
+PKG_SHLIB_DIRS= lib
+
+# Strip leading "${PREFIX}/" from the directory pathnames.
+_PKG_SHLIB_DIRS= ${PKG_SHLIB_DIRS:S|^${PREFIX}/||g}
+
+${_PKGTASKS_DATA.shlibs}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+ ${RUN}${TEST} "${RUN_LDCONFIG:tl}" != "yes" || \
+ ${ECHO} "# SHLIB: "${_PKG_SHLIB_DIRS:Q} >> ${.TARGET}.tmp
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
diff --git a/mk/pkgtasks/tests/Kyuafile b/mk/pkgtasks/tests/Kyuafile
new file mode 100644
index 00000000000..d904646df59
--- /dev/null
+++ b/mk/pkgtasks/tests/Kyuafile
@@ -0,0 +1,61 @@
+-- $NetBSD: Kyuafile,v 1.1 2017/06/01 02:06:05 jlam Exp $
+--[[-----------------------------------------------------------------------
+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.
+
+--]]-----------------------------------------------------------------------
+
+--[[-----------------------------------------------------------------------
+
+ The following variables will be used if they are set.
+
+ MAKE The name or path to the BSD make(1) utility. The default
+ is "make".
+
+ PKGSRCDIR
+ The location of the pkgsrc source tree. The default is
+ "/usr/pkgsrc".
+
+--]]-----------------------------------------------------------------------
+
+syntax( 2 )
+
+test_suite( "pkgsrc_pkgtasks" )
+
+atf_test_program { name = "create_usergroup_test",
+ required_programs = "perl" }
+atf_test_program { name = "directories_test" }
+atf_test_program { name = "files_test" }
+atf_test_program { name = "fonts_test" }
+atf_test_program { name = "groups_test" }
+atf_test_program { name = "info_files_test" }
+atf_test_program { name = "ocaml_findlib_test" }
+atf_test_program { name = "permissions_test" }
+atf_test_program { name = "pkgtasks_test" }
+atf_test_program { name = "shells_test" }
+atf_test_program { name = "shlibs_test" }
+atf_test_program { name = "users_test" }
diff --git a/mk/pkgtasks/tests/create_usergroup_test b/mk/pkgtasks/tests/create_usergroup_test
new file mode 100755
index 00000000000..9575fbd1cb2
--- /dev/null
+++ b/mk/pkgtasks/tests/create_usergroup_test
@@ -0,0 +1,169 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: create_usergroup_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# LOCALBASE
+# The location of the installation directory for packages.
+# The default is "/usr/pkg".
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+# TASK_MODULE_DIR
+# The location of the pkgtasks modules directory. The
+# default is "${LOCALBASE}/share/pkgtasks-1".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/usergroup.mk"
+
+all: create-usergroup
+
+pre-cmd: .PHONY
+ ${PRE_CMD.su-create-usergroup}; exit 1
+
+.PHONY: su-target
+su-target: .USE
+ ${RUN}${PRE_CMD.su-create-usergroup}; ${MAKE} su-${.TARGET}
+EOF
+}
+
+###
+### test1: pre-command check for existent group
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pre-command check for existent group"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+USERGROUP_PHASE= build
+PKG_GROUPS= wheel
+PERL5= perl
+EOF
+ ${MAKE} pre-cmd PKGSRCDIR="${PKGSRCDIR}" ||
+ atf_fail "existent group wasn't found"
+ atf_pass
+}
+
+###
+### test2: pre-command check for nonexistent group
+###
+
+atf_test_case test2
+
+test2_head()
+{
+ atf_set "descr" "pre-command check for nonexistent group"
+}
+
+test2_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+USERGROUP_PHASE= build
+PKG_GROUPS= nonexistent
+PERL5= perl
+EOF
+ ${MAKE} pre-cmd PKGSRCDIR="${PKGSRCDIR}"
+ [ $? -gt 0 ] || atf_fail "nonexistent group was found"
+ atf_pass
+}
+
+###
+### test3: create-usergroup
+###
+
+atf_test_case test3
+
+test3_head()
+{
+ : ${LOCALBASE:=/usr/pkg}
+ : ${TASK_MODULE_DIR:=${LOCALBASE}/share/pkgtasks-1}
+
+ atf_set "descr" "create-usergroup with existing group & user"
+ atf_set "require.files" "${TASK_MODULE_DIR}/load.subr"
+}
+
+test3_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+USERGROUP_PHASE= build
+PKG_CREATE_USERGROUP= no
+PKG_GROUPS= wheel
+PKG_USERS= root:wheel
+
+PERL5= perl
+PKGNAME= test-pkg
+SETENV= env
+SH= /bin/sh
+PKG_REFCOUNT_DBDIR= ${.CURDIR}/refcount
+EOF
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" ||
+ atf_fail "couldn't create groups and users"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+ atf_add_test_case test2
+ atf_add_test_case test3
+}
diff --git a/mk/pkgtasks/tests/directories_test b/mk/pkgtasks/tests/directories_test
new file mode 100755
index 00000000000..d38b411de78
--- /dev/null
+++ b/mk/pkgtasks/tests/directories_test
@@ -0,0 +1,111 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: directories_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/directories.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.directories}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/directories.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+MAKE_DIRS= ${PREFIX}/lib/modules
+OWN_DIRS= ${VARBASE}/test
+REQD_DIRS= ${PREFIX}/empty_dir
+MAKE_DIRS_PERMS= ${PREFIX}/lib/suid_modules root wheel 0700
+OWN_DIRS_PERMS= ${VARBASE}/secret root wheel 0700
+REQD_DIRS_PERMS= ${PREFIX}/unwriteable root wheel 0500
+EOF
+ # Expected output is each directory stripped of leading
+ # "${PREFIX}/" and inserted into the following template:
+ #
+ # # DIR: <dir> <flags> [<mode> [<user> [<group>]]]
+ #
+ cat > expected << 'EOF'
+# DIR: lib/modules m
+# DIR: lib/suid_modules m 0700 root wheel
+# DIR: /var/test mo
+# DIR: /var/secret mo 0700 root wheel
+# DIR: empty_dir fm
+# DIR: unwriteable fm 0500 root wheel
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/files_test b/mk/pkgtasks/tests/files_test
new file mode 100755
index 00000000000..42ef833c9ce
--- /dev/null
+++ b/mk/pkgtasks/tests/files_test
@@ -0,0 +1,168 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: files_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/files.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.files}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/files.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+FAIL_MSG= echo
+
+# Use config file directory with a package-specific subdirectory.
+PKG_SYSCONFDIR= /etc/${PKG_SYSCONFSUBDIR}
+PKG_SYSCONFSUBDIR= daemon
+PKG_SYSCONFDIR_PERMS= daemon daemon 0750
+
+CONF_FILES= ${PREFIX}/share/examples/daemon/conf ${PKG_SYSCONFDIR}/conf
+CONF_FILES_PERMS= ${PREFIX}/share/examples/daemon/private-conf \
+ ${PKG_SYSCONFDIR}/private-conf daemon daemon 0640
+REQD_FILES= /dev/null ${PREFIX}/libdata/empty
+REQD_FILES_PERMS= /dev/null ${PREFIX}/libdata/unwriteable daemon daemon 0440
+
+# init/rc.d.mk would turn "RCD_SCRIPTS=daemond daemon-authd" into the following.
+_INIT_SCRIPTS= share/examples/rc.d/daemond /etc/rc.d/daemond
+_INIT_SCRIPTS+= share/examples/rc.d/daemon-authd /etc/rc.d/daemon-authd
+EOF
+ # Expected output is each file path stripped of leading
+ # "${PREFIX}/" and inserted into the following template:
+ #
+ # # FILE: <target> <flags> <source> [<mode> [<user> [<group>]]]
+ #
+ cat > expected << 'EOF'
+# FILE: /etc/daemon/conf c share/examples/daemon/conf 0644
+# FILE: /etc/daemon/private-conf c share/examples/daemon/private-conf 0640 daemon daemon
+# FILE: libdata/empty cf /dev/null 0644
+# FILE: libdata/unwriteable cf /dev/null 0440 daemon daemon
+# FILE: /etc/rc.d/daemond cr share/examples/rc.d/daemond 0755
+# FILE: /etc/rc.d/daemon-authd cr share/examples/rc.d/daemon-authd 0755
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+###
+### test2
+###
+
+atf_test_case test2
+
+test2_head()
+{
+ atf_set "descr" "_pkgtasks-files-postinstall-check"
+}
+
+test2_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ # Setup
+ setup
+
+ # Create all of the source files to pass checks.
+ for n in 1 2 3 4 5 6 7 8 9; do
+ ( exec > source$n )
+ done
+
+ cat > mk.conf << 'EOF'
+FAIL_MSG= echo
+
+LOCALBASE= ${.CURDIR}
+DESTDIR= # empty
+
+CONF_FILES= source1 target1 source2 target2
+CONF_FILES_PERMS= source3 target3 u3 g3 0640 \
+ source4 target4 u4 g4 0640
+REQD_FILES= source5 target5 source6 target7
+REQD_FILES_PERMS= source8 target8 u8 g8 0400 \
+ source9 target9 u9 g9 0400
+EOF
+ ${MAKE} _pkgtasks-files-postinstall-check \
+ PKGSRCDIR="${PKGSRCDIR}" > output
+
+ if grep -cq "^" output; then
+ cat output
+ atf_fail "postinstall checks failed"
+ fi
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+ atf_add_test_case test2
+}
diff --git a/mk/pkgtasks/tests/fonts_test b/mk/pkgtasks/tests/fonts_test
new file mode 100755
index 00000000000..cfaaac32adb
--- /dev/null
+++ b/mk/pkgtasks/tests/fonts_test
@@ -0,0 +1,116 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: fonts_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/fonts.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.fonts}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/fonts.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+# X11 settings that affect ${X11_ENCODINGSDIR}.
+X11_TYPE= modular
+X11BASE= ${PREFIX}
+
+.for _util in mkfontdir mkfontscale ttmkfdir type1inst
+TOOLS_PATH.{_util}= ${PREFIX}/bin/${_util}
+.endfor
+
+FONTS_DIRS.ttf= ${PREFIX}/share/fonts/ttf1 \
+ ${PREFIX}/share/fonts/ttf2
+FONTS_DIRS.type1= ${PREFIX}/share/fonts/type1
+FONTS_DIRS.x11= ${PREFIX}/share/fonts/pcf \
+ ${PREFIX}/share/fonts/snf
+EOF
+ # Expected output is each path stripped of leading "${PREFIX}/"
+ # and inserted into the following template:
+ #
+ # # FONTS: <fontdir> <fonttype>
+ #
+ cat > expected << 'EOF'
+# FONTS: share/fonts/ttf1 ttf
+# FONTS: share/fonts/ttf2 ttf
+# FONTS: share/fonts/type1 type1
+# FONTS: share/fonts/pcf x11
+# FONTS: share/fonts/snf x11
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/groups_test b/mk/pkgtasks/tests/groups_test
new file mode 100755
index 00000000000..ecc4cfd29de
--- /dev/null
+++ b/mk/pkgtasks/tests/groups_test
@@ -0,0 +1,113 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: groups_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/usergroup.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.groups}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1: groups
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/usergroup.mk | groups"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > getgid.sh << 'EOF'
+case $1 in
+g1) echo 1 ;;
+g2) echo 2 ;;
+*) exit 1 ;;
+esac
+EOF
+ cat > mk.conf << 'EOF'
+USERGROUP_PHASE= configure
+PKG_GROUPS= g1 g2 g3
+
+SH= /bin/sh
+_GETGID_CMD= ${SH} getgid.sh
+EOF
+ # Expected output is each group inserted into the
+ # following template:
+ #
+ # # GROUP: <group>[:<gid>]
+ #
+ cat > expected << 'EOF'
+# GROUP: g1:1
+# GROUP: g2:2
+# GROUP: g3
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/info_files_test b/mk/pkgtasks/tests/info_files_test
new file mode 100755
index 00000000000..2b2b8a0f57a
--- /dev/null
+++ b/mk/pkgtasks/tests/info_files_test
@@ -0,0 +1,109 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: info_files_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/info_files.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.info_files}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/info_files.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+PKGINFODIR= share/info
+
+# Create mock ${INFO_FILES_cmd}.
+INFO_FILES= yes
+INFO_FILES_cmd= \
+ ( echo ${PKGINFODIR:Q}"/test1.info"; \
+ echo ${PKGINFODIR:Q}"/test2.info"; \
+ echo ${PKGINFODIR:Q}"/test3.info" )
+EOF
+ # Expected output is each path stripped of leading "${PREFIX}/"
+ # and inserted into the following template:
+ #
+ # # INFO: <file>
+ #
+ cat > expected << 'EOF'
+# INFO: share/info/test1.info
+# INFO: share/info/test2.info
+# INFO: share/info/test3.info
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/ocaml_findlib_test b/mk/pkgtasks/tests/ocaml_findlib_test
new file mode 100755
index 00000000000..77fcc9365c5
--- /dev/null
+++ b/mk/pkgtasks/tests/ocaml_findlib_test
@@ -0,0 +1,104 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: ocaml_findlib_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/ocaml_findlib.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.ocaml_findlib}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/ocaml_findlib.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+OCAML_FINDLIB_DIRS= bz2 dbm ldap sqlite3 odn
+EOF
+ # Expected output is each path stripped of leading "${PREFIX}/"
+ # and inserted into the following template:
+ #
+ # # FINDLIB: <directory>
+ #
+ cat > expected << 'EOF'
+# FINDLIB: bz2
+# FINDLIB: dbm
+# FINDLIB: ldap
+# FINDLIB: sqlite3
+# FINDLIB: odn
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/permissions_test b/mk/pkgtasks/tests/permissions_test
new file mode 100755
index 00000000000..f05aca651a5
--- /dev/null
+++ b/mk/pkgtasks/tests/permissions_test
@@ -0,0 +1,110 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: permissions_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/permissions.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.permissions}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/permissions.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+REAL_ROOT_USER= root
+REAL_ROOT_GROUP= wheel
+GAMES_USER= games
+GAMES_GROUP= games
+GAMEMODE= 2551
+GAMEDATAMODE= 664
+GAMEDIRMODE= 775
+
+SPECIAL_PERMS= ${PREFIX}/bin/sudo ${SETUID_ROOT_PERMS} \
+ ${PREFIX}/bin/tetris ${SETGID_GAMES_PERMS}
+EOF
+ # Expected output is each directory stripped of leading
+ # "${PREFIX}/" and inserted into the following template:
+ #
+ # # PERMS: <path> <mode> <owner> <group>
+ #
+ cat > expected << 'EOF'
+# PERMS: bin/sudo 4511 root wheel
+# PERMS: bin/tetris 2551 games games
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/pkgtasks_test b/mk/pkgtasks/tests/pkgtasks_test
new file mode 100755
index 00000000000..4799fc9e732
--- /dev/null
+++ b/mk/pkgtasks/tests/pkgtasks_test
@@ -0,0 +1,139 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: pkgtasks_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/bsd.pkgtasks.mk"
+
+all: value
+value: ${PKGTASKS_DATAFILE}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+
+.PHONY: depends
+depends: .PHONY
+ @${ECHO} ${DEPENDS:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/bsd.pkgtasks.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+MAKE_DIRS+= dir
+CONF_FILES+= source target
+PKG_GROUPS+= g1
+PKG_USERS+= u1:g1
+EOF
+ # Expected output.
+ cat > expected << 'EOF'
+# DIR: dir m
+# FILE: target c source 0644
+# GROUP: g1
+# USER: u1:g1:::/nonexistent:/sbin/nologin
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+###
+### test2
+###
+
+atf_test_case test2
+
+test2_head()
+{
+ atf_set "descr" "pkgtasks dependency"
+}
+
+test2_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+MAKE_DIRS+= dir
+CONF_FILES+= source target
+PKG_GROUPS+= g1
+PKG_USERS+= u1:g1
+EOF
+ ${MAKE} depends PKGSRCDIR="${PKGSRCDIR}" > output
+
+ cat output
+ grep -q "pkgtools/pkgtasks" output ||
+ atf_fail "pkgtasks dependency missing"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+ atf_add_test_case test2
+}
diff --git a/mk/pkgtasks/tests/shells_test b/mk/pkgtasks/tests/shells_test
new file mode 100755
index 00000000000..6778327ceac
--- /dev/null
+++ b/mk/pkgtasks/tests/shells_test
@@ -0,0 +1,104 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: shells_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/shells.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.shells}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/shells.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+PKG_SHELL= ${PREFIX}/bin/bash
+PKG_SHELL+= ${PREFIX}/bin/pdksh
+PKG_SHELL+= ${PREFIX}/bin/zsh
+EOF
+ # Expected output is each directory stripped of leading
+ # "${PREFIX}/" and inserted into the following template:
+ #
+ # # SHELL: <path>
+ #
+ cat > expected << 'EOF'
+# SHELL: bin/bash
+# SHELL: bin/pdksh
+# SHELL: bin/zsh
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/shlibs_test b/mk/pkgtasks/tests/shlibs_test
new file mode 100755
index 00000000000..e35ee9211f6
--- /dev/null
+++ b/mk/pkgtasks/tests/shlibs_test
@@ -0,0 +1,100 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: shlibs_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/shlibs.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.shlibs}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1
+###
+
+atf_test_case test1
+
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/shlibs.mk"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > mk.conf << 'EOF'
+SHLIB_TYPE= a.out
+EOF
+ # Expected output is each directory stripped of leading
+ # "${PREFIX}/" and inserted into the following template:
+ #
+ # # SHLIB: <directory> [...]
+ #
+ cat > expected << 'EOF'
+# SHLIB: lib
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/tests/test.mk b/mk/pkgtasks/tests/test.mk
new file mode 100644
index 00000000000..c0f9f509cf3
--- /dev/null
+++ b/mk/pkgtasks/tests/test.mk
@@ -0,0 +1,69 @@
+# $NetBSD: test.mk,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# Definitions used by pkgtasks/*.mk files that are not assigned default
+# values.
+#
+_PKGTASKS_DIR?= ${WRKDIR}/.pkgtasks
+CAT?= cat
+CP?= cp
+ECHO?= echo
+FAIL_MSG?= ${ECHO} "!!!"
+LOCALBASE?= /usr/pkg
+MKDIR?= mkdir -p
+MV?= mv
+NOLOGIN?= /sbin/nologin
+PKG_SYSCONFDIR?= /etc
+PREFIX?= ${LOCALBASE}
+RM?= rm
+RUN?= @
+SH?= /bin/sh
+STEP_MSG?= ${ECHO} ">>>"
+TEST?= test
+VARBASE?= /var
+
+_PKGTASKS_NEEDARGS= \
+ needargs() { \
+ if ${TEST} $$3 -lt $$2; then \
+ ${FAIL_MSG} "$$1 must have a multiple of $$2 words. Rest: $$4"; \
+ return 1; \
+ fi; \
+ }
+
+# Override any other default definitions so that generated files go into
+# the current directory.
+#
+WRKDIR= ${.CURDIR}
+
+.PHONY: all
+all: _all
+
+.PHONY: _all
+_all:
+ ${RUN}: "do nothing"
diff --git a/mk/pkgtasks/tests/users_test b/mk/pkgtasks/tests/users_test
new file mode 100755
index 00000000000..7e5a165bad2
--- /dev/null
+++ b/mk/pkgtasks/tests/users_test
@@ -0,0 +1,113 @@
+#!/usr/bin/env atf-sh
+#
+# $NetBSD: users_test,v 1.1 2017/06/01 02:06:05 jlam Exp $
+#
+# 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.
+
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MAKE The name or path to the BSD make(1) utility. The default
+# is "make".
+#
+# PKGSRCDIR
+# The location of the pkgsrc source tree. The default is
+# "/usr/pkgsrc".
+#
+
+setup()
+{
+ cat > Makefile << 'EOF'
+.include "${PKGSRCDIR}/mk/pkgtasks/tests/test.mk"
+.sinclude "mk.conf"
+.include "${PKGSRCDIR}/mk/pkgtasks/usergroup.mk"
+
+all: value
+value: ${_PKGTASKS_DATA.users}
+ ${RUN}${CP} ${.ALLSRC:Q} ${.TARGET:Q}
+EOF
+}
+
+###
+### test1: users
+###
+
+atf_test_case test1
+test1_head()
+{
+ atf_set "descr" "pkgsrc/mk/pkgtasks/usergroup.mk | users"
+}
+
+test1_body()
+{
+ : ${MAKE:=make}
+ : ${PKGSRCDIR:=/usr/pkgsrc}
+
+ setup
+
+ cat > getuid.sh << 'EOF'
+case $1 in
+u1) echo 1 ;;
+u2) echo 2 ;;
+*) exit 1 ;;
+esac
+EOF
+ cat > mk.conf << 'EOF'
+USERGROUP_PHASE= configure
+PKG_USERS= u1:g1 u2:g2 u3:g3
+PKG_GECOS.u3= test user u1 description
+
+SH= /bin/sh
+_GETUID_CMD= ${SH} getuid.sh
+EOF
+ # Expected output is each user:group inserted into the
+ # following template:
+ #
+ # # USER: <user>:<group>[:<uid>]
+ #
+ cat > expected << 'EOF'
+# USER: u1:g1:1::/nonexistent:/sbin/nologin
+# USER: u2:g2:2::/nonexistent:/sbin/nologin
+# USER: u3:g3::test user u1 description:/nonexistent:/sbin/nologin
+EOF
+ echo ">>> expected"
+ cat expected
+
+ ${MAKE} PKGSRCDIR="${PKGSRCDIR}" || atf_fail "make(1) failed"
+
+ echo ">>> value"
+ cat value
+
+ cmp expected value || atf_fail "expected differs from value"
+ atf_pass
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case test1
+}
diff --git a/mk/pkgtasks/usergroup.mk b/mk/pkgtasks/usergroup.mk
new file mode 100644
index 00000000000..5d3efe13e88
--- /dev/null
+++ b/mk/pkgtasks/usergroup.mk
@@ -0,0 +1,275 @@
+# $NetBSD: usergroup.mk,v 1.1 2017/06/01 02:06:04 jlam Exp $
+#
+# 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.
+
+# Generate the data file for the groups package task.
+
+# PKG_CREATE_USERGROUP
+# Whether to automatically update the system groups database.
+#
+# Possible: yes, no
+# Default: yes
+#
+_USER_VARS.pkgtasks+= PKG_CREATE_USERGROUP
+PKG_CREATE_USERGROUP?= yes
+FILES_SUBST+= PKG_CREATE_USERGROUP=${PKG_CREATE_USERGROUP:Q}
+
+# USERGROUP_PHASE
+# The phase just before which users and groups need to be created.
+# If not defined or empty, then by default, users and groups are
+# created when the binary package is installed as part of the
+# package tasks invoked.
+#
+# Possible: configure, build, pre-install
+# Default: (empty)
+#
+_PKG_VARS.pkgtasks+= USERGROUP_PHASE
+USERGROUP_PHASE?= # empty
+_USERGROUP_PHASES= configure build pre-install
+
+.if !empty(USERGROUP_PHASE) && empty(_USERGROUP_PHASES:M${USERGROUP_PHASE})
+PKG_FAIL_REASON+= "USERGROUP_PHASE must be one of: ${_USERGROUP_PHASES}"
+.endif
+
+# PKG_GROUPS
+# List of group names that should be added or removed from the
+# system group database.
+#
+# PKG_GID.<group>
+# The numeric group ID for the named group. If not defined or
+# empty, then this variable is set by the infrastructure and it
+# may be used in phases after and including ${USERGROUP_PHASE}.
+#
+# Possible: any valid group ID
+# Default: (empty)
+#
+# PKG_USERS
+# List of pairs of usernames and group names for users that
+# should be added or removed from the system users database. The
+# pairs are of the form: <user>:<group>.
+#
+# PKG_UID.<user>
+# The numeric user ID for the named user. If not defined or
+# empty, then this variable is set by the infrastructure if
+# ${USERGROUP_PHASE} is non-empty, and it may be used in phases
+# after and including ${USERGROUP_PHASE}.
+#
+# Possible: any valid user ID
+# Default: (empty)
+#
+# PKG_GECOS.<user>
+# The description for the user.
+#
+# Possible: any string not containing ':' (colon, ASCII 58)
+# Default: (empty)
+#
+# PKG_HOME.<user>
+# The home directory for the user.
+#
+# Possible: any valid pathname
+# Default: ${_PKG_USER_HOME} (set in platform/${OPSYS}.mk)
+#
+# PKG_SHELL.<user>
+# The login shell for the user.
+#
+# Possible: any login shell
+# Default: ${_PKG_USER_SHELL) (set in platform/${OPSYS}.mk)
+#
+_PKG_VARS.pkgtasks+= PKG_GROUPS PKG_USERS
+_PKG_VARS.pkgtasks+= ${PKG_GROUPS:@g@PKG_GID.${g}@}
+_PKG_VARS.pkgtasks+= ${PKG_USERS:@u@PKG_UID.${u:C/\:.*$//}@}
+_PKG_VARS.pkgtasks+= ${PKG_USERS:@u@PKG_GECOS.${u:C/\:.*$//}@}
+_PKG_VARS.pkgtasks+= ${PKG_USERS:@u@PKG_HOME.${u:C/\:.*$//}@}
+_PKG_VARS.pkgtasks+= ${PKG_USERS:@u@PKG_SHELL.${u:C/\:.*$//}@}
+
+PKG_GROUP?= # empty
+PKG_USERS?= # empty
+
+_PKG_USER_HOME?= /nonexistent
+_PKG_USER_SHELL?= ${NOLOGIN}
+FILES_SUBST+= PKG_USER_HOME=${_PKG_USER_HOME:Q}
+FILES_SUBST+= PKG_USER_SHELL=${_PKG_USER_SHELL:Q}
+
+.if !empty(PKG_USERS:N*\:*)
+PKG_FAIL_REASON+= ${PKG_USERS:N*\:*:Q}" in PKG_USERS should be <user>:<group>"
+.endif
+
+# USE_GAMESGROUP
+# Whether the package uses a "games" group. If ${USE_GAMESGROUP}
+# is "yes", then the following variables may be used when
+# installing setgid games and their data files:
+#
+# GAMES_USER
+# GAMES_GROUP
+# GAMEMODE
+# SETGID_GAMES_PERMS
+#
+# SETGIDGAME is deprecated, but use its value if USE_GAMESGROUP is not
+# defined.
+#
+_PKG_VARS.pkgtasks+= USE_GAMEGROUP
+#USE_GAMESGROUP?= # empty
+USE_GAMESGROUP?= ${SETGIDGAME}
+.if ${USE_GAMESGROUP:tl} == "yes"
+PKG_GROUPS+= ${GAMES_GROUP}
+PKG_USERS+= ${GAMES_USER}:${GAMES_GROUP}
+_BUILD_DEFS+= GAMES_GROUP GAMES_USER GAMEDATAMODE GAMEDIRMODE GAMEMODE
+.endif
+
+.if !defined(OPSYS) && !empty(OPSYS:MInterix)
+. for _user_ in ${PKG_USERS:C/\\\\//g:C/:.*//}
+. if !empty(PKG_GROUPS:M${_user_})
+PKG_FAIL_REASON+= "User and group '${_user_}' cannot be the same name on Interix".
+. endif
+. endfor
+.endif
+
+# Trigger dependency on pkgtasks if needed.
+_PKGTASKS_DATAVARS.groups= PKG_GROUPS
+_PKGTASKS_DATAVARS.users= PKG_USERS
+.for _var_ in ${_PKGTASKS_DATAVARS.groups} ${_PKGTASKS_DATAVARS.users}
+. if !empty(${_var_})
+USE_PKGTASKS= yes
+. endif
+.endfor
+
+# Add dependency on useradd/groupadd package as needed.
+# TODO: Implement more platforms' useradd and groupadd in "pkgtasks".
+#
+.if !empty(PKG_USERS) || !empty(PKG_GROUPS)
+DEPENDS+= ${_USER_DEPENDS}
+.endif
+
+# Shell commands used to determine the numeric GIDs and UIDs of
+# groups and users on the system.
+#
+_GETGID_CMD?= ${PERL5} -le 'print scalar getgrnam shift'
+_GETUID_CMD?= ${PERL5} -le 'print scalar getpwnam shift'
+
+# Split out ${_PKG_GROUP.<user>} for each entry in ${PKG_USERS}.
+_PKG_USERS= ${PKG_USERS:C/:.*$//}
+.for _entry_ in ${PKG_USERS}
+. for _user_ in ${_entry_:C/:.*$//g}
+_PKG_GROUP.${_user_}= ${_entry_:C/^.*://g}
+. endfor
+.endfor
+
+.if !empty(USERGROUP_PHASE)
+. for _group_ in ${PKG_GROUPS}
+_USERGROUP_TOOLS= perl
+PKG_GID.${_group_}?= ${_PKG_GID.${_group_}}
+_PKG_GID.${_group_}= ${_PKG_GID.${_group_}_cmd:sh:M*}
+_PKG_GID.${_group_}_cmd= \
+ ( ${_GETGID_CMD} ${_group_:Q} ) 2>/dev/null || ${ECHO} ""
+. endfor
+. for _user_ in ${_PKG_USERS}
+_USERGROUP_TOOLS= perl
+PKG_UID.${_user_}?= ${_PKG_UID.${_user_}}
+_PKG_UID.${_user_}= ${_PKG_UID.${_user_}_cmd:sh:M*}
+_PKG_UID.${_user_}_cmd= \
+ ( ${_GETUID_CMD} ${_user_:Q} ) 2>/dev/null || ${ECHO} ""
+. endfor
+_PKG_GROUPDATA= ${PKG_GROUPS:@g@${g:Q}:${PKG_GID.${g}:Q}@:C/:*$//g}
+_PKG_USERDATA= ${_PKG_USERS:@u@${u:Q}:${_PKG_GROUP.${u}:Q}:${PKG_UID.${u}:Q}:${PKG_GECOS.${u}:Q}:${PKG_HOME.${u}:U${_PKG_USER_HOME}:Q}:${PKG_SHELL.${u}:U${_PKG_USER_SHELL}:Q}@:C/:*$//g}
+_USERGROUP_EXISTS= \
+ ( set -- args \
+ ${PKG_GROUPS:@g@${_PKG_GID.${g}:Q}"" ${PKG_GID.${g}:Q}""@} \
+ ${_PKG_USERS:@u@${_PKG_UID.${u}:Q}"" ${PKG_UID.${u}:Q}""@}; \
+ shift; while [ $$\# -gt 0 ]; do \
+ real="$$1"; requested="$$2"; shift 2; \
+ [ -n "$$real" -a "$$real" = "$$requested" ] || exit 1; \
+ done; exit 0 )
+
+.else
+_PKG_GROUPDATA= ${PKG_GROUPS}
+_PKG_USERDATA= ${_PKG_USERS:@u@${u:Q}:${_PKG_GROUP.${u}:Q}::${PKG_GECOS.${u}:Q}:${PKG_HOME.${u}:U${_PKG_USER_HOME}:Q}:${PKG_SHELL.${u}:U${_PKG_USER_SHELL}:Q}@:C/:*$//g}
+_USERGROUP_EXISTS= ( : "make create-usergroup"; exit 1 )
+.endif
+
+_USERGROUP_TOOLS?= # empty
+USE_TOOLS+= ${_USERGROUP_TOOLS}
+
+_PKGTASKS_DATA.groups= ${_PKGTASKS_DIR}/groups
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.groups}
+
+${_PKGTASKS_DATA.groups}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+ ${RUN}set -- args ${_PKG_GROUPDATA}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ entry="$$1"; shift; \
+ ${ECHO} "# GROUP: $$entry" >> ${.TARGET}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
+
+_PKGTASKS_DATA.users= ${_PKGTASKS_DIR}/users
+_PKGTASKS_DATAFILES+= ${_PKGTASKS_DATA.users}
+
+${_PKGTASKS_DATA.users}:
+ ${RUN}${MKDIR} ${.TARGET:H:Q}
+ ${RUN}exec > ${.TARGET}.tmp
+ ${RUN}set -- args ${_PKG_USERDATA}; shift; \
+ while ${TEST} "$$#" -gt 0; do \
+ entry="$$1"; shift; \
+ ${ECHO} "# USER: $$entry" >> ${.TARGET}.tmp; \
+ done
+ ${RUN}${MV} ${.TARGET:Q}.tmp ${.TARGET:Q}
+
+# create-usergroup
+# make(1) target to create any required groups and users.
+#
+.PHONY: create-usergroup
+create-usergroup: su-target
+ @${STEP_MSG} "Requiring users and groups for "${PKGNAME:Q}
+
+_PKGTASKS_USERGROUP= ${PKGSRCDIR}/mk/pkgtasks/usergroup.sh
+_PKGTASKS_ENV= PKGNAME=${PKGNAME:Q} \
+ PKG_CREATE_USERGROUP=${PKG_CREATE_USERGROUP:Q} \
+ PKG_PREFIX=${PREFIX:Q} \
+ PKG_REFCOUNT_DBDIR=${PKG_REFCOUNT_DBDIR:Q} \
+ TASK_MODULE_DIR=${TASK_MODULE_DIR:Q} \
+ TASK_PLATFORM=${OPSYS:Q}
+
+PRE_CMD.su-create-usergroup= \
+ if ${_USERGROUP_EXISTS}; then \
+ ${ECHO} "All groups and users already exist."; \
+ exit 0; \
+ fi
+
+.PHONY: su-create-usergroup
+su-create-usergroup: ${_PKGTASKS_DATA.groups} ${_PKGTASKS_DATA.users}
+ ${RUN}${SETENV} ${_PKGTASKS_ENV} ${SH} ${_PKGTASKS_USERGROUP:Q} \
+ ${_PKGTASKS_DATA.groups:Q} ${_PKGTASKS_DATA.users:Q}
+
+.if !empty(USERGROUP_PHASE:Mconfigure)
+pre-configure: create-usergroup
+.elif !empty(USERGROUP_PHASE:Mbuild)
+pre-build: create-usergroup
+.elif !empty(USERGROUP_PHASE:Mpre-install)
+pre-install: create-usergroup
+.endif
diff --git a/mk/pkgtasks/usergroup.sh b/mk/pkgtasks/usergroup.sh
new file mode 100644
index 00000000000..6fe377eec83
--- /dev/null
+++ b/mk/pkgtasks/usergroup.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+#
+# 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
+# usergroup.sh -- add and check for groups and users
+#
+# SYNOPSIS
+# usergroup.sh <groupdata> <userdata>
+#
+# DESCRIPTION
+# usergroup.sh ensures that all required groups and users as
+# listed in the datafiles exist.
+#
+# The datafiles contains lines of the format needed by the
+# "group" and "users" tasks.
+#
+# EXIT STATUS
+# Exits 0 if the groups and users all exist, and >0 otherwise.
+#
+
+: ${LOCALBASE:=/usr/pkg}
+: ${TASK_MODULE_DIR:=${LOCALBASE}/share/pkgtasks-1}
+. "${TASK_MODULE_DIR}/load.subr"
+
+: ${TASK_PLATFORM:=NetBSD}
+
+task_load groups
+task_load users
+task_load usergroup_${TASK_PLATFORM}
+
+do_usergroup()
+{
+ [ $# -ge 2 ] || return 127
+ local groupdata="$1"; shift
+ local userdata="$1"; shift
+
+ [ -f "$groupdata" ] || return 1
+ [ -f "$userdata" ] || return 1
+
+ local result=0
+
+ # Groups
+ if [ $result -eq 0 ]; then
+ task_groups add < $groupdata || result=1
+ task_groups check-add < $groupdata || result=1
+ fi
+
+ # Users
+ if [ $result -eq 0 ]; then
+ task_users add < $userdata || result=1
+ task_users check-add < $userdata || result=1
+ fi
+
+ return $result
+}
+
+do_usergroup "$@"