diff options
Diffstat (limited to 'usr.sbin/bsdconfig/usermgmt')
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/INDEX | 60 | ||||
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/Makefile | 17 | ||||
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/USAGE | 33 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/groupadd | 64 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/groupdel | 93 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/groupedit | 93 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/groupinput | 295 | ||||
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/include/Makefile | 11 | ||||
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/include/group_input.subr | 437 | ||||
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/include/messages.subr | 111 | ||||
-rw-r--r-- | usr.sbin/bsdconfig/usermgmt/include/user_input.subr | 1180 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/useradd | 64 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/userdel | 93 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/useredit | 93 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/userinput | 515 | ||||
-rwxr-xr-x | usr.sbin/bsdconfig/usermgmt/usermgmt | 150 |
16 files changed, 3309 insertions, 0 deletions
diff --git a/usr.sbin/bsdconfig/usermgmt/INDEX b/usr.sbin/bsdconfig/usermgmt/INDEX new file mode 100644 index 0000000..81e43aa --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/INDEX @@ -0,0 +1,60 @@ +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ + +# +# Title that will be shown on the bsdconfig menu +menu_title="Login/Group Management" +# +# a short descriptive line shown at the bottom of the bsdconfig menu. +# keep it short because any line longer than the terminal width will +# be truncated. +menu_help="Manage system user and/or group information" +# +# two-part variable that defines an action to take when 'keyword' +# is passed on a bsdconfig command line. variable takes the form +# "keyword|command" and multiple occurrences of the variable +# (with different 'keyword's, or different 'keyword's AND 'command's) +# are allowed. If 'command' begins with a '/' then the full +# path to the program is needed. If 'command' begins with anything +# else it is a path relative to the directory this INDEX file is in. +# 'keyword' can be i18n'ed but 'command' is the name of a script. +menu_selection="usermgmt|usermgmt" +menu_selection="useradd|useradd" +menu_selection="useredit|useredit" +menu_selection="userdel|userdel" +menu_selection="groupmgmt|usermgmt" +menu_selection="groupadd|groupadd" +menu_selection="groupedit|groupedit" +menu_selection="groupdel|groupdel" +# +# Items below this line do NOT need i18n translation---------------------- +# +# Name of the program to be run when this menu choice is selected. +# if it begins with a '/' then the full path to the program is needed. +# if it begins with anything else it is a path relative to the directory +# this INDEX file is in. +menu_program="usermgmt" diff --git a/usr.sbin/bsdconfig/usermgmt/Makefile b/usr.sbin/bsdconfig/usermgmt/Makefile new file mode 100644 index 0000000..7c1b3e5 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= groupadd groupdel groupedit groupinput \ + useradd userdel useredit userinput usermgmt + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdconfig/usermgmt/USAGE b/usr.sbin/bsdconfig/usermgmt/USAGE new file mode 100644 index 0000000..9aa4dca --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/USAGE @@ -0,0 +1,33 @@ +# Copyright (c) 2012 Devin Teske +# All Rights Reserved. +# +# 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INLUDING, 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. +# +# $FreeBSD$ + +Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS] + +OPTIONS: + -h Print usage statement and exit. + -S Secure X11 mode (implies `-X'). As root, always prompt-for + and validate sudo(8) username/password before starting. + -X Use Xdialog(1) in place of dialog(1). diff --git a/usr.sbin/bsdconfig/usermgmt/groupadd b/usr.sbin/bsdconfig/usermgmt/groupadd new file mode 100755 index 0000000..c4f4fde --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupadd @@ -0,0 +1,64 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr + +APP_DIR="070.usermgmt" + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Chain-load to groupinput to centralize code and minimize duplication +# +f_dialog_init +$BSDCFG_LIBE/$APP_DIR/groupinput ${USE_XDIALOG:+-X} mode="Add" + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/groupdel b/usr.sbin/bsdconfig/usermgmt/groupdel new file mode 100755 index 0000000..aa5a71d --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupdel @@ -0,0 +1,93 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include $BSDCFG_LIBE/$APP_DIR/include/group_input.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Initialize +# +f_dialog_init +f_dialog_title "$msg_delete $msg_group" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init + +# +# Loop until the user Exits, Cancels or presses ESC +# +while :; do + f_dialog_menu_group_list + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + "X $msg_exit") break ;; + + *) # anything else is a group name + $BSDCFG_LIBE/$APP_DIR/groupinput \ + ${USE_XDIALOG:+-X} mode="Delete" group="$mtag" + ;; + + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/groupedit b/usr.sbin/bsdconfig/usermgmt/groupedit new file mode 100755 index 0000000..beb11af --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupedit @@ -0,0 +1,93 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include $BSDCFG_LIBE/$APP_DIR/include/group_input.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Initialize +# +f_dialog_init +f_dialog_title "$msg_edit_view $msg_group" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init + +# +# Loop until the user Exits, Cancels or presses ESC +# +while :; do + f_dialog_menu_group_list + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + "X $msg_exit") break ;; + + *) # anything else is a group name + $BSDCFG_LIBE/$APP_DIR/groupinput \ + ${USE_XDIALOG:+-X} mode="Edit/View" group="$mtag" + ;; + + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/groupinput b/usr.sbin/bsdconfig/usermgmt/groupinput new file mode 100755 index 0000000..96186be --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupinput @@ -0,0 +1,295 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include $BSDCFG_LIBE/$APP_DIR/include/group_input.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# set some reasonable defaults if /etc/adduser.conf does not exist. +[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf +: ${passwdtype:="yes"} + +############################################################ FUNCTIONS + +# save_changes +# +# Save any/all settings (actions performed depend on $mode value). +# +save_changes() +{ + local err retval=$SUCCESS + + case "$mode" in + Delete) + err=$( pw groupdel "$group_name" 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_error" "$err" + return $retval + fi + f_show_msg "$msg_group_deleted" + ;; + Add) + local cmd="pw groupadd -n '$group_name'" + [ "$group_gid" ] && cmd="$cmd -g '$group_gid'" + [ "$group_members" != "$cur_group_members" ] && + cmd="$cmd -M '$group_members'" + if [ "$pw_group_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$group_password" ]; then + cmd="echo \"\$group_password\" | $cmd -h 0" + fi + f_dprintf "cmd=$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_error" "$err" + return $retval + fi + f_show_msg "$msg_group_added" + ;; + Edit/View) + local cmd="pw groupmod -n '$group_name'" + [ "$group_gid" ] && cmd="$cmd -g '$group_gid'" + [ "$group_members" != "$cur_group_members" ] && + cmd="$cmd -M '$group_members'" + if [ "$pw_group_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$group_password" ]; then + cmd="echo \"\$group_password\" | $cmd -h 0" + fi + f_dprintf "cmd=$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_error" "$err" + return $retval + fi + f_show_msg "$msg_group_updated" + ;; + esac + + save_flag= + return $SUCCESS +} + +# dialog_title_update $mode +# +# Set the title based on the given $mode. +# +dialog_title_update() +{ + local mode="$1" + case "$mode" in + Add) f_dialog_title "$msg_add $msg_group" ;; + Edit/View) f_dialog_title "$msg_edit_view $msg_group: $group" ;; + Delete) f_dialog_title "$msg_delete $msg_group: $group" ;; + esac +} + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while [ $# -gt 0 ]; do + key="${1%%=*}" + value="${1#*=}" + f_dprintf "key=[$key] value=[$value]" + case "$key" in + mode) mode="$value";; + group) group="$value";; + esac + shift +done +f_dprintf "mode=[$mode] group=[$group]" + +# +# Initialize +# +f_dialog_init +dialog_title_update "$mode" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init +menu_text= +save_flag= +hline="$hline_arrows_tab_enter" + +if [ "$mode" = "Add" ]; then + # + # Ask a series of questions to pre-fill the editor screen. + # + # The defaults used in each dialog should allow the user to simply + # hit ENTER to proceed, because cancelling a single dialog will + # cause them to be returned to the main groupmenu. + # + + f_dialog_input_group_name || exit 0 + [ "$passwdtype" = "yes" ] && + { f_dialog_input_group_password || exit 0; } + f_dialog_input_group_gid || exit 0 + f_dialog_input_group_members || exit 0 +fi + +if [ "$mode" = "Edit/View" -o "$mode" = "Delete" ]; then + f_input_group "$group" || f_die 1 "$msg_group_not_found" +fi + +cur_group_name="$group_name" +cur_group_password="$group_password" +cur_group_gid="$group_gid" +cur_group_members="$group_members" + +[ "$mode" = "Delete" ] && save_flag=1 + +# +# Loop until the user decides to Exit, Cancel, or presses ESC +# +while :; do + dialog_title_update "$mode" + + menu_text= + menu_exit="$msg_exit" + if [ "$save_flag" ]; then + if [ "$mode" = "Delete" ]; then + menu_exit="$msg_delete/$msg_exit" + menu_text="$msg_delete_exit_or_cancel" + else + menu_exit="$msg_save/$msg_exit" + menu_text="$msg_save_exit_or_cancel" + fi + fi + + case "$mode" in + Delete) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_group: $group_name' + '-' '$msg_password: -----' + '-' '$msg_group_id: $group_gid' + '-' '$msg_group_members: $group_members' + " # END-QUOTE + ;; + *) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_group: $group_name' + '2' '$msg_password: -----' + '3' '$msg_group_id: $group_gid' + '4' '$msg_group_members: $group_members' + " # END-QUOTE + esac + + size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$menu_text\" \ + \"\$hline\" \ + $menu_items ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$menu_text\" $size \ + $menu_items \ + 2> $DIALOG_TMPDIR/dialog.menu.$$ + + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + # Exit if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || f_die + + case "$mtag" in + X) # Exit + if [ "$save_flag" ]; then + save_changes || continue + fi + break + ;; + 1) # Group Name + case "$mode" in + Add) f_dialog_input_group_name "$group_name" ;; + Edit/View|Delete) + f_dialog_menu_group_list + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + # Loop if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || continue + + [ "$mtag" = "X $msg_exit" ] && continue + + group="$mtag" + f_input_group "$group" || f_die 1 "$msg_group_not_found" + cur_group_name="$group_name" + cur_group_password="$group_password" + cur_group_gid="$group_gid" + cur_group_members="$group_members" + [ "$mode" != "Delete" ] && save_flag= + esac + ;; + 2) # Password + f_dialog_input_group_password + ;; + 3) # GID + f_dialog_input_group_gid "$group_gid" + ;; + 4) # Users in Group + f_dialog_input_group_members "$group_members" + ;; + esac + +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/include/Makefile b/usr.sbin/bsdconfig/usermgmt/include/Makefile new file mode 100644 index 0000000..15f88aa --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt/include +FILES= group_input.subr messages.subr user_input.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdconfig/usermgmt/include/group_input.subr b/usr.sbin/bsdconfig/usermgmt/include/group_input.subr new file mode 100644 index 0000000..b4121b1 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/include/group_input.subr @@ -0,0 +1,437 @@ +if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1 +# +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/strings.subr +f_include_lang $BSDCFG_LIBE/include/messages.subr + +APP_DIR="070.usermgmt" +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +############################################################ FUNCTIONS + +# f_input_group $group +# +# Given $group name or id, create the environment variables group_name, +# group_gid, and group_members (and group_password is reset to NULL). +# +f_input_group() +{ + eval $( pw groupshow "$1" | awk -F: ' + { + printf "group_name='\'%s\''\n", $1 + printf "group_password=\n" + printf "group_gid='\'%s\''\n", $3 + printf "group_members='\'%s\''\n", $4 + exit + }' ) +} + +# f_dialog_menu_group_list +# +# Allows the user to select a group from a list. +# +f_dialog_menu_group_list() +{ + local menu_list size + local hline="$hline_alnum_punc_tab_enter" + + menu_list=" + 'X $msg_exit' '' + " # END-QUOTE + + # Add groups from group(5) + menu_list="$menu_list $( pw groupshow -a | awk -F: ' + !/^[[:space:]]*(#|$)/ { + printf "'\'%s\'\ \'%s\''\n", $1, $1 + }' + )" + + size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\" \ + \"\$hline\" \ + $menu_list ) + + eval $DIALOG \ + --clear --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\" $size $menu_list \ + 2> "$DIALOG_TMPDIR/dialog.menu.$$" +} + +# f_dialog_input_group_name [$group_name] +# +# Allows the user to enter a new groupname for a given group. If the user does +# not cancel or press ESC, the $group_name variable will hold the +# newly-configured value upon return. +# +# If $cur_group_name is defined, the user can enter that and by-pass error- +# checking (allowing the user to "revert" to an old value without, for example, +# being told that the groupname already exists). +# +f_dialog_input_group_name() +{ + local msg="$( printf "$msg_group" )" + local hline="$hline_alnum_tab_enter" + + # + # Loop until the user provides taint-free/valid input + # + local size retval _name="$1" _input="$1" + while :; do + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + # Check for no-change + [ "$_input" = "$_name" ] && return $SUCCESS + + # Check for reversion + if [ "$_input" = "$cur_group_name" ]; then + group_name="$cur_group_name" + return $SUCCESS + fi + + # Check for NULL entry + if [ ! "$_input" ]; then + f_show_msg "$msg_group_is_empty" + continue + fi + + # Check for invalid entry + if ! echo "$_input" | grep -q "^[[:alpha:]]"; then + f_show_msg "$msg_group_must_start_with_letter" + continue + fi + + # Check for duplicate entry + if f_quietly pw groupshow -n "$_input"; then + f_show_msg "$msg_group_already_used" "$_input" + continue + fi + + group_name="$_input" + break + done + save_flag=1 + + f_dprintf "group_name: [$cur_group_name]->[$group_name]" + + return $SUCCESS +} + +# f_dialog_input_group_password +# +# Prompt the user to enter a password (twice). +# +f_dialog_input_group_password() +{ + local hline="$hline_alnum_punc_tab_enter" + local msg size rmsg rsize + + msg=$( printf "$msg_group_password" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "" \ + "$hline" ) + + rmsg=$( printf "$msg_reenter_group_password" ) + rsize=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$rmsg" \ + "" \ + "$hline" ) + + # + # Loop until the user provides taint-free/valid input + # + local retval _password1 _password2 + while :; do + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --insecure \ + --passwordbox \"\$msg\" $size \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _password1=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --insecure \ + --passwordbox \"\$rmsg\" $rsize \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _password2=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + # Check for password mismatch + if [ "$_password1" != "$_password2" ]; then + f_show_msg "$msg_group_passwords_do_not_match" + continue + fi + + # Check for NULL entry + if [ ! "$_password1" ]; then + f_dialog_yesno \ + "$msg_disable_password_auth_for_group" || + continue + pw_group_password_disable=1 + else + pw_group_password_disable= + fi + + group_password="$_password1" + break + done + save_flag=1 + + f_dprintf "group_password: [$cur_group_password]->[$group_password]" + + return $SUCCESS +} + +# f_dialog_input_group_gid [$group_gid] +# +# Allow the user to enter a new GID for a given group. If the user does not +# cancel or press ESC, the $group_gid variable will hold the newly-configured +# value upon return. +# +f_dialog_input_group_gid() +{ + local msg size retval _input="$1" + local hline="$hline_num_tab_enter" + + msg=$( printf "$msg_group_id_leave_empty_for_default" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + group_gid="$_input" + save_flag=1 + + f_dprintf "group_gid: [$cur_group_gid]->[$group_gid]" + + return $SUCCESS +} + +# f_dialog_input_group_members [$group_members] +# +# Allow the user to modify a list of members for a given group. If the user does +# not cancel or press ESC, the $group_members variable will hold the newly- +# configured value upon return. +# +f_dialog_input_group_members() +{ + local menu_choice msg size retval _input="$1" + local hline="$hline_num_arrows_tab_enter" + local user + local menu_list + local all_users_valid + local _group_members + local checklist_users + + menu_list=" + 'X' '$msg_continue' + '1' '$msg_select_group_members_from_list' + '2' '$msg_enter_group_members_manually' + " # END-QUOTE + + while :; do + msg="$msg_group_members:" + menu_size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$msg\" \ + \"\$hline\" \ + $menu_list ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$msg\" $menu_size \ + $menu_list \ + 2> $DIALOG_TMPDIR/dialog.menu.$$ + retval=$? + menu_choice=$( f_dialog_menutag ) + f_dprintf "retval=$retval menu_choice=[$menu_choice]" + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + case "$menu_choice" in + X) # Exit + break ;; + 1) # Select Group Members from a list + user_list=$( pw usershow -a | awk -F: ' + !/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' ) + checklist_users= + for user in $user_list; do + checklist_users="$checklist_users $user \"\"" + if echo "$_input" | grep -q "\<$user\>"; then + checklist_users="$checklist_users on" + else + checklist_users="$checklist_users off" + fi + done + + size=$( eval f_dialog_radiolist_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\" \ + \"\$hline\" \ + $checklist_users ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --separate-output \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --checklist \"\$msg\" $size \ + $checklist_users \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + _group_members=$( f_dialog_inputstr | tr '\n' ' ' | + sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' ) + + # Return to previous menu if user has either + # pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input="$_group_members" + ;; + 2) # Enter Group Members manually + hline="$hline_num_tab_enter" + msg=$( + printf "$msg_group_members ($msg_separated_by_commas)" + ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _group_members=$( f_dialog_inputstr ) + + # Return to previous menu if user has either + # pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input="$_group_members" + ;; + esac + done + + group_members="$_input" + save_flag=1 + f_dprintf "group_members: [$cur_group_members]->[$group_members]" + + return $SUCCESS +} + +fi # ! $_USERMGMT_GROUP_INPUT_SUBR diff --git a/usr.sbin/bsdconfig/usermgmt/include/messages.subr b/usr.sbin/bsdconfig/usermgmt/include/messages.subr new file mode 100644 index 0000000..e2e7bf3 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/include/messages.subr @@ -0,0 +1,111 @@ +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ + +hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER" +hline_alnum_tab_enter="Use alpha-numeric, TAB or ENTER" +hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER" +hline_arrows_tab_enter="Press arrows, TAB or ENTER" +hline_num_arrows_tab_enter="Use numbers, arrows, TAB or ENTER" +hline_num_tab_enter="Use numbers, TAB or ENTER" +msg_account_expires_in_how_many_days="Account expires in how many days?" +msg_account_expires_on="Account Expires on" +msg_account_does_not_expire="Account does not expire" +msg_add="Add" +msg_add_group="Add Group" +msg_add_login="Add Login" +msg_cancel="Cancel" +msg_continue="Continue" +msg_create_dotfiles="Create Dotfiles" +msg_create_home_directory="Create Home Directory" +msg_delete="Delete" +msg_delete_exit_or_cancel="Choose Delete/Exit when finished or Cancel." +msg_delete_group="Delete Group" +msg_delete_home_directory="Delete Home Directory" +msg_delete_login="Delete Login" +msg_delete_primary_group="Delete Primary Group" +msg_deleting_home_directory="Deleting home directory..." +msg_disable_password_auth_for_account="Disable password authentication for this account?" +msg_disable_password_auth_for_group="Disable password authentication for this group?" +msg_edit_date_time_with_a_calendar="Edit date/time with a calendar" +msg_edit_group="Edit/View Group" +msg_edit_login="Edit/View Login" +msg_edit_view="Edit/View" +msg_enter_group_members_manually="Enter Group Members manually" +msg_enter_number_of_days_into_the_future="Enter number of days into the future" +msg_enter_value_manually="Edit value manually" +msg_error="ERROR!" +msg_exit="Exit" +msg_full_name="Full Name" +msg_group="Group" +msg_group_added="Group Added" +msg_group_already_used="%s: Group is already used." +msg_group_deleted="Group Deleted" +msg_group_is_empty="Group is empty." +msg_group_id="Group ID" +msg_group_id_leave_empty_for_default="Group ID (Leave empty for default)" +msg_group_members="Group Members" +msg_group_must_start_with_letter="Group must start with a letter." +msg_group_not_found="%s: Group not found." +msg_group_password="Group Password" +msg_group_passwords_do_not_match="Group Passwords do not match." +msg_group_updated="Group Updated" +msg_home_directory="Home Directory" +msg_invalid_number_of_days="Invalid number of days." +msg_invalid_number_of_seconds="Invalid number of seconds." +msg_login="Login" +msg_login_added="Login Added" +msg_login_already_used="%s: Login is already used." +msg_login_class="Login Class" +msg_login_deleted="Login Deleted" +msg_login_is_empty="Login is empty." +msg_login_management="Login/Group Management" +msg_login_must_start_with_letter="Login must start with a letter." +msg_login_not_found="Login not found." +msg_login_updated="Login Updated" +msg_member_of_groups="Member of Groups" +msg_n_a="N/A" +msg_number_of_seconds_since_epoch="Number of seconds since the Epoch\n(1 = %s)\nNULL or zero to disable:" +msg_no="No" +msg_ok="OK" +msg_password="Password" +msg_password_expires_in_how_many_days="Password expires in how many days?" +msg_password_expires_on="Password Expires on" +msg_passwords_do_not_match="Passwords do not match." +msg_password_does_not_expire="Password does not expire" +msg_reenter_group_password="Re-enter Group Password" +msg_reenter_password="Re-enter Password" +msg_save="Save" +msg_save_exit_or_cancel="Choose Save/Exit when finished or Cancel." +msg_separated_by_commas="Separated by commas" +msg_select_group_members_from_list="Select Group Members from a list" +msg_select_login_shell="Select Login Shell" +msg_shell="Shell" +msg_user="User" +msg_user_id="UID" +msg_user_id_leave_empty_for_default="UID (Leave empty for default)" +msg_warning="WARNING!" +msg_yes="Yes" diff --git a/usr.sbin/bsdconfig/usermgmt/include/user_input.subr b/usr.sbin/bsdconfig/usermgmt/include/user_input.subr new file mode 100644 index 0000000..a522f9d --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/include/user_input.subr @@ -0,0 +1,1180 @@ +if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1 +# +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/strings.subr +f_include_lang $BSDCFG_LIBE/include/messages.subr + +APP_DIR="070.usermgmt" +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +############################################################ CONFIGURATION + +# +# Default location of shells(5) +# +: ${ETC_SHELLS:=/etc/shells} + +############################################################ FUNCTIONS + +# f_get_member_groups $user +# +# Get a list of additional groups $user is a member of in group(5). +# +f_get_member_groups() +{ + echo $( pw groupshow -a | awk -F: "/[:,]$1(,|\$)/{print \$1}" ) +} + +# f_input_user $user +# +# Given $user name or id, create the environment variables pw_name, pw_uid, +# pw_gid, pw_class, pw_password_expire, pw_account_expire, pw_gecos, +# pw_home_dir, pw_shell, and pw_member_groups (and pw_password is reset to +# NULL). +# +f_input_user() +{ + local user="$1" + eval $( pw usershow "$user" | awk -F: ' + { + printf "pw_name='\'%s\''\n", $1 + printf "pw_password=\n" + printf "pw_uid='\'%s\''\n", $3 + printf "pw_gid='\'%s\''\n", $4 + printf "pw_class='\'%s\''\n", $5 + printf "pw_password_expire='\'%s\''\n", $6 + printf "pw_account_expire='\'%s\''\n", $7 + printf "pw_gecos='\'%s\''\n", $8 + printf "pw_home_dir='\'%s\''\n", $9 + printf "pw_shell='\'%s\''\n", $10 + }' ) + pw_member_groups=$( f_get_member_groups "$user" ) +} + +# f_dialog_menu_user_list +# +# Allows the user to select a login from a list. +# +f_dialog_menu_user_list() +{ + local menu_list size + local hline="$hline_alnum_punc_tab_enter" + + menu_list=" + 'X $msg_exit' '' + " # END-QUOTE + + # Add users from passwd(5) + menu_list="$menu_list $( pw usershow -a | awk -F: ' + !/^[[:space:]]*(#|$)/ { + printf "'\'%s\'\ \'%s\''\n", $1, $8 + }' + )" + + size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\" \ + \"\$hline\" \ + $menu_list ) + + eval $DIALOG \ + --clear --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\" $size $menu_list \ + 2> "$DIALOG_TMPDIR/dialog.menu.$$" +} + +# f_dialog_input_member_groups [$member_groups] +# +# Allows the user to edit group memberships for a given user. If the user does +# not cancel or press ESC, the $pw_member_groups variable will hold the newly- +# configured value upon return. +# +f_dialog_input_member_groups() +{ + local msg="$( printf "$msg_member_of_groups" )" + local hline="$hline_alnum_tab_enter" + + # + # Loop until the user provides taint-free/valid input + # + local size retval all_groups checklist_groups="" _member_groups="$1" + all_groups=$( pw groupshow -a | awk -F: ' + !/^[[:space:]]*(#|$)/ { + printf "%s\n", $1 + }' + ) + for grp in $all_groups; do + checklist_groups="$checklist_groups $grp $grp" + if echo "$_member_groups" | grep -q "\<$grp\>"; then + checklist_groups="$checklist_groups on" + else + checklist_groups="$checklist_groups off" + fi + done + + while :; do + size=$( eval f_dialog_radiolist_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\" \ + \"\$hline\" \ + $checklist_groups ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --separate-output \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --checklist \"\$msg\" $size \ + $checklist_groups \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _member_groups=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + # + # Validate each of the groups the user has entered + # + local group all_groups_valid=1 + for group in $_member_groups; do + if ! f_quietly pw groupshow -n "$group"; then + f_show_msg "$msg_group_not_found" "$group" + all_groups_valid= + break + fi + done + [ "$all_groups_valid" ] || continue + + pw_member_groups="$_member_groups" + break + done + save_flag=1 + + local debug="pw_member_groups:" + f_dprintf "$debug [$cur_pw_member_groups]->[$pw_member_groups]" + + return $SUCCESS +} + +# f_dialog_input_name [$name] +# +# Allows the user to enter a new username for a given user. If the user does +# not cancel or press ESC, the $pw_name variable will hold the newly-configured +# value upon return. +# +# If $cur_pw_name is defined, the user can enter that and by-pass error- +# checking (allowing the user to "revert" to an old value without, for example, +# being told that the username already exists). +# +f_dialog_input_name() +{ + local msg="$( printf "$msg_login" )" + local hline="$hline_alnum_tab_enter" + + # + # Loop until the user provides taint-free/valid input + # + local size retval _name="$1" _input="$1" + while :; do + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + # Check for no-change + [ "$_input" = "$_name" ] && return $SUCCESS + + # Check for reversion + if [ "$_input" = "$cur_pw_name" ]; then + pw_name="$cur_pw_name" + return $SUCCESS + fi + + # Check for NULL entry + if [ ! "$_input" ]; then + f_show_msg "$msg_login_is_empty" + continue + fi + + # Check for invalid entry + if ! echo "$_input" | grep -q "^[[:alpha:]]"; then + f_show_msg "$msg_login_must_start_with_letter" + continue + fi + + # Check for duplicate entry + if f_quietly pw usershow -n "$_input"; then + f_show_msg "$msg_login_already_used" "$_input" + continue + fi + + pw_name="$_input" + break + done + save_flag=1 + + f_dprintf "pw_name: [$cur_pw_name]->[$pw_name]" + + return $SUCCESS +} + +# f_dialog_input_password +# +# Prompt the user to enter a password (twice). +# +f_dialog_input_password() +{ + local hline="$hline_alnum_punc_tab_enter" + local msg size rmsg rsize + + msg=$( printf "$msg_password" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "" \ + "$hline" ) + + rmsg=$( printf "$msg_reenter_password" ) + rsize=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$rmsg" \ + "" \ + "$hline" ) + + # + # Loop until the user provides taint-free/valid input + # + local retval _password1 _password2 + while :; do + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --insecure \ + --passwordbox \"\$msg\" $size \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _password1=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --insecure \ + --passwordbox \"\$rmsg\" $rsize \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _password2=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + # Check for password mismatch + if [ "$_password1" != "$_password2" ]; then + f_show_msg "$msg_passwords_do_not_match" + continue + fi + + # Check for NULL entry + if [ ! "$_password1" ]; then + f_dialog_yesno \ + "$msg_disable_password_auth_for_account" || + continue + pw_password_disable=1 + else + pw_password_disable= + fi + + pw_password="$_password1" + break + done + save_flag=1 + + f_dprintf "pw_password: [$cur_pw_password]->[$pw_password]" + + return $SUCCESS +} + +# f_dialog_input_gecos [$gecos] +# +# Allow the user to enter new GECOS information for a given user. This +# information is commonly used to store the ``Full Name'' of the user. If the +# user does not cancel or press ESC, the $pw_gecos variable will hold the +# newly-configured value upon return. +# +f_dialog_input_gecos() +{ + local msg size retval _input="$1" + local hline="$hline_alnum_punc_tab_enter" + + msg=$( printf "$msg_full_name" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + pw_gecos="$_input" + save_flag=1 + + f_dprintf "pw_gecos: [$cur_pw_gecos]->[$pw_gecos]" + + return $SUCCESS +} + +# f_dialog_input_uid [$uid] +# +# Allow the user to enter a new UID for a given user. If the user does not +# cancel or press ESC, the $pw_uid variable will hold the newly-configured +# value upon return. +# +f_dialog_input_uid() +{ + local msg size retval _input="$1" + local hline="$hline_num_tab_enter" + + msg=$( printf "$msg_user_id_leave_empty_for_default" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + pw_uid="$_input" + save_flag=1 + + f_dprintf "pw_uid: [$cur_pw_uid]->[$pw_uid]" + + return $SUCCESS +} + +# f_dialog_input_gid [$gid] +# +# Allow the user to enter a new primary GID for a given user. If the user does +# not cancel or press ESC, the $pw_gid variable will hold the newly-configured +# value upon return. +# +f_dialog_input_gid() +{ + local msg size retval _input="$1" + local hline="$hline_num_tab_enter" + + msg=$( printf "$msg_group_id_leave_empty_for_default" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + pw_gid="$_input" + save_flag=1 + + f_dprintf "pw_gid: [$cur_pw_gid]->[$pw_gid]" + + return $SUCCESS +} + +# f_dialog_input_class [$class] +# +# Allow the user to enter a new login class for a given user. If the user does +# not cancel or press ESC, the $pw_class variable will hold the newly- +# configured value upon return. +# +f_dialog_input_class() +{ + local msg size retval _input="$1" + local hline="$hline_alnum_tab_enter" + + msg=$( printf "$msg_login_class" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + pw_class="$_input" + save_flag=1 + + f_dprintf "pw_class: [$cur_pw_class]->[$pw_class]" + + return $SUCCESS +} + +# f_dialog_input_change [$seconds] +# +# Allow the user to enter a date/time (in number-of-seconds since the `epoch') +# for when a given user's password must be changed. If the user does not cancel +# or press ESC, the $pw_password_expire variable will hold the newly- +# configured value upon return. +# +f_dialog_input_change() +{ + local calendar_size timebox_size + local msg menu_size size retval _input="$1" + local hline="$hline_num_arrows_tab_enter" + + local menu_list=" + '1' '$msg_password_does_not_expire' + '2' '$msg_edit_date_time_with_a_calendar' + '3' '$msg_enter_number_of_days_into_the_future' + '4' '$msg_enter_value_manually' + " # END-QUOTE + + # + # Loop until the user provides taint-free/cancellation-free input + # + while :; do + msg="$msg_password_expires_on" + menu_size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$msg\" \ + \"\$hline\" \ + $menu_list ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$msg\" $menu_size \ + $menu_list \ + 2> $DIALOG_TMPDIR/dialog.menu.$$ + retval=$? + date_type=$( f_dialog_menutag ) + f_dprintf "retval=$retval date_type=[$date_type]" + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + case "$date_type" in + 1) # Password does not expire + _input="" + break ;; + + 2) # Edit date/time with a calendar + local _input_date _input_time ret_date ret_time + + local secs="$_input" + { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= + _input_date=$( date -j -f "%s" -- "$secs" \ + "+%d %m %Y" 2> /dev/null ) + calendar_size=$( f_dialog_calendar_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$hline" ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --calendar \"\$msg\" $calendar_size \ + $_input_date \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + ret_date=$( f_dialog_inputstr ) + f_dprintf "retval=$retval ret_date=[$ret_date]" + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input_time= + [ "$secs" ] && _input_time=$( date -j \ + -f %s -- "$_input" "+%H %M %S" 2> /dev/null ) + timebox_size=$( f_dialog_timebox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$hline" ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --timebox \"\$msg\" $timebox_size \ + $_input_time \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + ret_time=$( f_dialog_inputstr ) + f_dprintf "retval=$retval ret_time=[$ret_time]" + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input=$( date \ + -j -f "%d/%m/%Y %T" \ + -- "$ret_date $ret_time" \ + +%s 2> /dev/null ) + f_dprintf "_input=[$_input]" + break ;; + + 3) # Enter number of days into the future + local ret_days seconds="$( date +%s )" + + f_isinteger "$_input" || _input=0 + [ $_input -gt 0 -a $_input -gt $seconds ] && + ret_days=$(( ( $_input - $seconds ) / 86400 )) + f_isinteger "$ret_days" && + ret_days=$(( $ret_days + 1 )) + + msg="$msg_password_expires_in_how_many_days" + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$ret_days" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$ret_days\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + ret_days=$( f_dialog_inputstr ) + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + # Taint-check the user's input + if ! f_isinteger "$ret_days"; then + f_show_msg "$msg_invalid_number_of_days" + continue + fi + + f_dprintf "ret_days=[$ret_days]" + case "$ret_days" in + [-+]*) _input=$( date -v${ret_days}d +%s );; + 0) _input=$( date +%s );; + *) _input=$( date -v+${ret_days}d +%s );; + esac + f_dprintf "_input=[$_input]" + break ;; + + 4) # Enter value manually + local ret_secs + + msg=$( printf "$msg_number_of_seconds_since_epoch" \ + "$( date -r 1 "+%c %Z" )" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + ret_secs=$( f_dialog_inputstr ) + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input="$ret_secs" + + # Taint-check the user's input + if ! f_isinteger "${_input:-0}"; then + f_show_msg "$msg_invalid_number_of_seconds" + continue + fi + + f_dprintf "_input=[$_input]" + break ;; + + esac + + done # Loop forever + + pw_password_expire="$_input" + save_flag=1 + + local debug=pw_password_expire + f_dprintf "$debug: [$cur_pw_password_expire]->[$pw_password_expire]" + + return $SUCCESS +} + +# f_dialog_input_expire [$seconds] +# +# Allow the user to enter a date/time (in number-of-seconds since the `epoch') +# for when a given user's account should become expired. If the user does not +# cancel or press ESC, the $pw_account_expire variable will hold the newly- +# configured value upon return. +# +f_dialog_input_expire() +{ + local calendar_size timebox_size + local msg menu_size size retval _input="$1" + local hline="$hline_num_arrows_tab_enter" + + local menu_list=" + '1' '$msg_account_does_not_expire' + '2' '$msg_edit_date_time_with_a_calendar' + '3' '$msg_enter_number_of_days_into_the_future' + '4' '$msg_enter_value_manually' + " # END-QUOTE + + # + # Loop until the user provides taint-free/cancellation-free input + # + while :; do + msg="$msg_account_expires_on" + menu_size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$msg\" \ + \"\$hline\" \ + $menu_list ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$msg\" $menu_size \ + $menu_list \ + 2> $DIALOG_TMPDIR/dialog.menu.$$ + retval=$? + date_type=$( f_dialog_menutag ) + f_dprintf "retval=$retval date_type=[$date_type]" + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + case "$date_type" in + 1) # Account does not expire + _input="" + break ;; + + 2) # Edit date/time with a calendar + local _input_date _input_time ret_date ret_time + + local secs="$_input" + { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= + _input_date=$( date -j -f "%s" -- "$secs" \ + "+%d %m %Y" 2> /dev/null ) + calendar_size=$( f_dialog_calendar_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$hline" ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --calendar \"\$msg\" $calendar_size \ + $_input_date \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + ret_date=$( f_dialog_inputstr ) + f_dprintf "retval=$retval ret_date=[$ret_date]" + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input_time= + [ "$secs" ] && _input_time=$( date -j \ + -f %s -- "$_input" "+%H %M %S" 2> /dev/null ) + timebox_size=$( f_dialog_timebox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$hline" ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --timebox \"\$msg\" $timebox_size \ + $_input_time \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + ret_time=$( f_dialog_inputstr ) + f_dprintf "retval=$retval ret_time=[$ret_time]" + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input=$( date \ + -j -f "%d/%m/%Y %T" \ + -- "$ret_date $ret_time" \ + +%s 2> /dev/null ) + f_dprintf "_input=[$_input]" + break ;; + + 3) # Enter number of days into the future + local ret_days seconds="$( date +%s )" + + f_isinteger "$_input" || _input=0 + [ $_input -gt 0 -a $_input -gt $seconds ] && + ret_days=$(( ( $_input - $seconds ) / 86400 )) + f_isinteger "$ret_days" && + ret_days=$(( $ret_days + 1 )) + + msg="$msg_account_expires_in_how_many_days" + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$ret_days" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$ret_days\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + retval=$? + ret_days=$( f_dialog_inputstr ) + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + # Taint-check the user's input + if ! f_isinteger "$ret_days"; then + f_show_msg "$msg_invalid_number_of_days" + continue + fi + + f_dprintf "ret_days=[$ret_days]" + case "$ret_days" in + [-+]*) _input=$( date -v${ret_days}d +%s );; + 0) _input=$( date +%s );; + *) _input=$( date -v+${ret_days}d +%s );; + esac + f_dprintf "_input=[$_input]" + break ;; + + 4) # Enter value manually + local ret_secs + + msg=$( printf "$msg_number_of_seconds_since_epoch" \ + "$( date -r 1 "+%c %Z" )" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + ret_secs=$( f_dialog_inputstr ) + + # Return to menu if either ESC or Cancel/No + [ $retval -eq $SUCCESS ] || continue + + _input="$ret_secs" + + # Taint-check the user's input + if ! f_isinteger "${_input:-0}"; then + f_show_msg "$msg_invalid_number_of_seconds" + continue + fi + + f_dprintf "_input=[$_input]" + break ;; + + esac + + done # Loop forever + + pw_account_expire="$_input" + save_flag=1 + + local debug=pw_account_expire + f_dprintf "$debug: [$cur_pw_account_expire]->[$pw_account_expire]" + + return $SUCCESS +} + +# f_dialog_input_home_dir [$home_dir] +# +# Allow the user to enter a new home directory for a given user. If the user +# does not cancel or press ESC, the $pw_home_dir variable will hold the newly- +# configured value upon return. +# +f_dialog_input_home_dir() +{ + local msg size retval _input="$1" + local hline="$hline_alnum_punc_tab_enter" + + msg=$( printf "$msg_home_directory" ) + size=$( f_dialog_inputbox_size \ + "$DIALOG_TITLE" \ + "$DIALOG_BACKTITLE" \ + "$msg" \ + "$_input" \ + "$hline" ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --inputbox \"\$msg\" $size \ + \"\$_input\" \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + pw_home_dir="$_input" + save_flag=1 + + f_dprintf "pw_home_dir: [$cur_pw_home_dir]->[$pw_home_dir]" + + return $SUCCESS +} + +# f_dialog_input_home_create +# +# Prompt the user to confirm creation of a given user's home directory. If the +# user does not cancel (by choosing "No") or press ESC, the $pw_home_create +# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return +# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. +# +f_dialog_input_home_create() +{ + local retval + + f_dialog_yesno "$msg_create_home_directory" + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_home_create="$msg_yes" + else + pw_home_create="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_home_create: [$cur_pw_home_create]->[$pw_home_create]" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_group_delete +# +# Prompt the user to confirm deletion of a given user's primary group. If the +# user does not cancel (by choosing "No") or press ESC, the $pw_group_delete +# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return +# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. +# +f_dialog_input_group_delete() +{ + local retval + + if f_isinteger "$pw_gid"; then + if [ $pw_gid -lt 1000 ]; then + f_dialog_noyes "$msg_delete_primary_group" + else + f_dialog_yesno "$msg_delete_primary_group" + fi + elif [ "$pw_gid" ]; then + local gid=0 + gid=$( pw groupshow "$pw_gid" | awk -F: '{print $3}' ) + if f_isinteger "$gid" && [ $gid -lt 1000 ]; then + f_dialog_noyes "$msg_delete_primary_group" + else + f_dialog_yesno "$msg_delete_primary_group" + fi + else + f_dialog_yesno "$msg_delete_primary_group" + fi + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_group_delete="$msg_yes" + else + pw_group_delete="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_group_delete: [$cur_pw_group_delete]->[$pw_group_delete]" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_home_delete +# +# Prompt the user to confirm deletion of a given user's home directory. If the +# user does not cancel (by choosing "No") or press ESC, the $pw_home_delete +# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return +# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. +# +f_dialog_input_home_delete() +{ + local retval + + f_dialog_yesno "$msg_delete_home_directory" + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_home_delete="$msg_yes" + else + pw_home_delete="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_home_delete: [$cur_pw_home_delete]->[$pw_home_delete]" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_dotfiles_create +# +# Prompt the user to confirm population of a given user's home directory with +# sample dotfiles. If the user does not cancel (by choosing "No") or press ESC, +# the $pw_dotfiles_create variable will hold $msg_yes upon return, otherwise +# $msg_no. Use these return variables ($msg_yes and $msg_no) for comparison to +# be i18n-compatible. +# +f_dialog_input_dotfiles_create() +{ + local retval + + f_dialog_yesno "$msg_create_dotfiles" + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_dotfiles_create="$msg_yes" + else + pw_dotfiles_create="$msg_no" + fi + save_flag=1 + + local debug="pw_dotfiles_create:" + f_dprintf "$debug: [$cur_pw_dotfiles_create]->[$pw_dotfiles_create]" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_shell [$shell] +# +# Allow the user to select a new login shell for a given user. If the user does +# not cancel or press ESC, the $pw_home_dir variable will hold the newly- +# configured value upon return. +# +# +f_dialog_input_shell() +{ + local size retval shells shell_list _input="$1" + local hline="$hline_arrows_space_tab_enter" + local prompt="$msg_select_login_shell" + + shells=$( awk '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" ) + shell_list=$( + for shell in $shells; do + if [ "$shell" = "$_input" ]; then + echo "'$shell' '' 'on'" + else + echo "'$shell' '' 'off'" + fi + done + ) + + size=$( eval f_dialog_radiolist_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$prompt\" \ + \"\$hline\" \ + $shell_list ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --radiolist \"\$prompt\" $size \ + $shell_list \ + 2> $DIALOG_TMPDIR/dialog.inputbox.$$ + + retval=$? + _input=$( f_dialog_inputstr ) + + # Return if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || return $retval + + pw_shell="$_input" + save_flag=1 + + f_dprintf "pw_shell: [$cur_pw_shell]->[$pw_shell]" + + return $SUCCESS +} + +fi # ! $_USERMGMT_USER_INPUT_SUBR diff --git a/usr.sbin/bsdconfig/usermgmt/useradd b/usr.sbin/bsdconfig/usermgmt/useradd new file mode 100755 index 0000000..8dc1934 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/useradd @@ -0,0 +1,64 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr + +APP_DIR="070.usermgmt" + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Chain-load to userinput to centralize code and minimize duplication +# +f_dialog_init +$BSDCFG_LIBE/$APP_DIR/userinput ${USE_XDIALOG:+-X} mode="Add" + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/userdel b/usr.sbin/bsdconfig/usermgmt/userdel new file mode 100755 index 0000000..49a54c4 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/userdel @@ -0,0 +1,93 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include $BSDCFG_LIBE/$APP_DIR/include/user_input.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Initialize +# +f_dialog_init +f_dialog_title "$msg_delete $msg_login" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init + +# +# Loop until the user Exits, Cancels or presses ESC +# +while :; do + f_dialog_menu_user_list + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + "X $msg_exit") break ;; + + *) # anything else is a userid + $BSDCFG_LIBE/$APP_DIR/userinput \ + ${USE_XDIALOG:+-X} mode="Delete" user="$mtag" + ;; + + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/useredit b/usr.sbin/bsdconfig/usermgmt/useredit new file mode 100755 index 0000000..3109d36 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/useredit @@ -0,0 +1,93 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include $BSDCFG_LIBE/$APP_DIR/include/user_input.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Initialize +# +f_dialog_init +f_dialog_title "$msg_edit_view $msg_login" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init + +# +# Loop until the user Exits, Cancels or presses ESC +# +while :; do + f_dialog_menu_user_list + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + "X $msg_exit") break ;; + + *) # anything else is a userid + $BSDCFG_LIBE/$APP_DIR/userinput \ + ${USE_XDIALOG:+-X} mode="Edit/View" user="$mtag" + ;; + + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/userinput b/usr.sbin/bsdconfig/usermgmt/userinput new file mode 100755 index 0000000..43a750e --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/userinput @@ -0,0 +1,515 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include $BSDCFG_LIBE/$APP_DIR/include/user_input.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# set some reasonable defaults if /etc/adduser.conf does not exist. +[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf +: ${passwdtype:="yes"} +: ${homeprefix:="/home"} +: ${defaultshell:="/bin/sh"} +: ${udotdir:="/usr/share/skel"} + +############################################################ FUNCTIONS + +# copy_dotfiles +# +# Copy `skel' dot-files to a new home directory. +# +copy_dotfiles() +{ + ( # Operate within sub-shell to protect CWD/glob of parent + cd "$udotdir" || exit $? + set +f # glob + for file in dot.*; do + cp -n "$file" "$pw_home_dir/${file#dot}" || exit $? + done + ) +} + +# save_changes +# +# Save any/all settings (actions performed depend on $mode value). +# +save_changes() +{ + local err retval=$SUCCESS + + case "$mode" in + Delete) + err=$( pw userdel -u "$pw_uid" 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_error" "$err" + return $retval + fi + f_show_msg "$msg_login_deleted" + + if [ "$pw_group_delete" = "$msg_yes" ] && + f_quietly pw groupshow -g "$pw_gid" + then + err=$( pw groupdel -g "$pw_gid" 2>&1 ) || + f_show_msg "%s %s\n" "$msg_warning" "$err" + fi + + if [ "$pw_home_delete" = "$msg_yes" ]; then + f_dialog_info "$msg_deleting_home_directory" + err=$( rm -Rf "$pw_home_dir" 2>&1 ) || + f_show_msg "%s %s\n" "$msg_warning" "$err" + fi + ;; + Add) + local cmd="pw useradd -n '$pw_name'" + [ "$pw_member_groups" ] && cmd="$cmd -G '$pw_member_groups'" + [ "$pw_class" ] && cmd="$cmd -L '$pw_class'" + [ "$pw_gecos" ] && cmd="$cmd -c '$pw_gecos'" + [ "$pw_home_dir" ] && cmd="$cmd -d '$pw_home_dir'" + [ "$pw_account_expire" ] && cmd="$cmd -e '$pw_account_expire'" + [ "$pw_gid" ] && cmd="$cmd -g '$pw_gid'" + [ "$pw_password_expire" ] && cmd="$cmd -p '$pw_password_expire'" + [ "$pw_shell" ] && cmd="$cmd -s '$pw_shell'" + [ "$pw_uid" ] && cmd="$cmd -u '$pw_uid'" + if [ "$pw_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$pw_password" ]; then + cmd="echo \"\$pw_password\" | $cmd -h 0" + fi + f_dprintf "cmd=$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_error" "$err" + return $retval + fi + f_show_msg "$msg_login_added" + + if [ "$pw_home_create" = "$msg_yes" ]; then + err=$( mkdir -p "$pw_home_dir" 2>&1 ) + if [ $? -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_warning" "$err" + elif [ -e "$pw_home_dir" ]; then + err=$( chown -R "$pw_uid:$pw_gid" \ + "$pw_home_dir" 2>&1 ) + [ $? -eq $SUCCESS ] || f_show_msg \ + "%s %s\n" "$msg_warning" "$err" + fi + fi + + if [ "$pw_dotfiles_create" = "$msg_yes" ]; then + err=$( copy_dotfiles 2>&1 ) || + f_show_msg "%s %s\n" "$msg_warning" "$err" + fi + + user="$pw_name" + f_quietly pw usershow -n "$pw_name" && + mode="Edit/View" # Change mode + ;; + Edit/View) + local cmd="pw usermod -n '$pw_name'" + [ "$pw_member_groups" ] && cmd="$cmd -G '$pw_member_groups'" + [ "$pw_class" ] && cmd="$cmd -L '$pw_class'" + [ "$pw_gecos" ] && cmd="$cmd -c '$pw_gecos'" + [ "$pw_home_dir" ] && cmd="$cmd -d '$pw_home_dir'" + [ "$pw_account_expire" ] && cmd="$cmd -e '$pw_account_expire'" + [ "$pw_gid" ] && cmd="$cmd -g '$pw_gid'" + [ "$pw_password_expire" ] && cmd="$cmd -p '$pw_password_expire'" + [ "$pw_shell" ] && cmd="$cmd -s '$pw_shell'" + [ "$pw_uid" ] && cmd="$cmd -u '$pw_uid'" + if [ "$pw_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$pw_password" ]; then + cmd="echo \"\$pw_password\" | $cmd -h 0" + fi + f_dprintf "cmd=$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_error" "$err" + return $retval + fi + f_show_msg "$msg_login_updated" + + if [ "$pw_home_create" = "$msg_yes" ]; then + err=$( mkdir -p "$pw_home_dir" ) + if [ $? -ne $SUCCESS ]; then + f_show_msg "%s %s\n" "$msg_warning" "$err" + elif [ -e "$pw_home_dir" ]; then + err=$( chown -R "$pw_uid:$pw_gid" \ + "$pw_home_dir" 2>&1 ) + [ $? -eq $SUCCESS ] || f_show_msg \ + "%s %s\n" "$msg_warning" "$err" + fi + fi + + if [ "$pw_dotfiles_create" = "$msg_yes" ]; then + err=$( copy_dotfiles 2>&1 ) || + f_show_msg "%s %s\n" "$msg_warning" "$err" + fi + ;; + esac + + save_flag= + return $SUCCESS +} + +# dialog_title_update $mode +# +# Set the title based on the given $mode. +# +dialog_title_update() +{ + local mode="$1" + case "$mode" in + Add) f_dialog_title "$msg_add $msg_user" ;; + Edit/View) f_dialog_title "$msg_edit_view $msg_user: $user" ;; + Delete) f_dialog_title "$msg_delete $msg_user: $user" ;; + esac +} + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while [ $# -gt 0 ]; do + key="${1%%=*}" + value="${1#*=}" + f_dprintf "key=[$key] value=[$value]" + case "$key" in + mode) mode="$value";; + user) user="$value";; + esac + shift +done +f_dprintf "mode=[$mode] user=[$user]" + +# +# Initialize +# +f_dialog_init +dialog_title_update "$mode" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init +menu_text= +save_flag= +hline="$hline_arrows_tab_enter" + +if [ "$mode" = "Add" ]; then + # + # Ask a series of questions to pre-fill the editor screen. + # + # The defaults used in each dialog should allow the user to simply + # hit ENTER to proceed, because cancelling a single dialog will + # cause them to be returned to the main usermenu. + # + + f_dialog_input_name || exit 0 + f_dialog_input_gecos "$pw_name" || exit 0 + [ "$passwdtype" = "yes" ] && + { f_dialog_input_password || exit 0; } + f_dialog_input_uid || exit 0 + f_dialog_input_gid || exit 0 + f_dialog_input_member_groups || exit 0 + f_dialog_input_class || exit 0 + f_dialog_input_change || exit 0 + f_dialog_input_expire || exit 0 + f_dialog_input_home_dir "$homeprefix/$pw_name" || exit 0 + pw_dotfiles_create="$msg_no" + if [ ! -d "$homeprefix/$pw_name" ]; then + f_dialog_input_home_create || exit 0 + [ "$pw_home_create" = "$msg_yes" ] && + { f_dialog_input_dotfiles_create || exit 0; } + fi + f_dialog_input_shell "$defaultshell" || exit 0 +fi + +if [ "$mode" = "Edit/View" -o "$mode" = "Delete" ]; then + f_input_user "$user" || f_die 1 "$msg_login_not_found" +fi + +if [ "$mode" = "Edit/View" ]; then + [ -d "$pw_home_dir" ] || pw_home_create="$msg_no" + pw_dotfiles_create="$msg_no" +fi + +if [ "$mode" = "Delete" ]; then + f_dialog_input_group_delete || exit 0 + pw_home_delete="$msg_no" + [ -d "$pw_home_dir" ] && + { f_dialog_input_home_delete || exit 0; } +fi + +cur_pw_name="$pw_name" +cur_pw_password="$pw_password" +cur_pw_uid="$pw_uid" +cur_pw_gid="$pw_gid" +cur_pw_member_groups="$pw_member_groups" +cur_pw_class="$pw_class" +cur_pw_password_expire="$pw_password_expire" +cur_pw_account_expire="$pw_account_expire" +cur_pw_gecos="$pw_gecos" +cur_pw_home_dir="$pw_home_dir" +cur_pw_shell="$pw_shell" +cur_pw_group_delete="$pw_group_delete" +cur_pw_home_create="$pw_home_create" +cur_pw_home_delete="$pw_home_delete" +cur_pw_dotfiles_create="$pw_dotfiles_create" + +[ "$mode" = "Delete" ] && save_flag=1 + +# +# Loop until the user decides to Exit, Cancel, or presses ESC +# +while :; do + dialog_title_update "$mode" + + menu_text= + menu_exit="$msg_exit" + if [ "$save_flag" ]; then + if [ "$mode" = "Delete" ]; then + menu_exit="$msg_delete/$msg_exit" + menu_text="$msg_delete_exit_or_cancel" + else + menu_exit="$msg_save/$msg_exit" + menu_text="$msg_save_exit_or_cancel" + fi + fi + + pw_password_expires_on="$pw_password_expire" + f_isinteger "$pw_password_expire" && [ $pw_password_expire -ne 0 ] && + pw_password_expires_on=$( + date -r "$pw_password_expire" "+%F %T %Z" + ) + pw_account_expires_on="$pw_account_expire" + f_isinteger "$pw_account_expire" && [ "$pw_account_expire" -ne 0 ] && + pw_account_expires_on=$( + date -r "$pw_account_expire" "+%F %T %Z" + ) + + case "$mode" in + Delete) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_login: $pw_name' + '-' '$msg_full_name: $pw_gecos' + '-' '$msg_password: -----' + '-' '$msg_user_id: $pw_uid' + '-' '$msg_group_id: $pw_gid' + '-' '$msg_member_of_groups: $pw_member_groups' + '-' '$msg_login_class: $pw_class' + '-' '$msg_password_expires_on: $pw_password_expires_on' + '-' '$msg_account_expires_on: $pw_account_expires_on' + '-' '$msg_home_directory: $pw_home_dir' + '-' '$msg_shell: $pw_shell' + " # END-QUOTE + ;; + *) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_login: $pw_name' + '2' '$msg_full_name: $pw_gecos' + '3' '$msg_password: -----' + '4' '$msg_user_id: $pw_uid' + '5' '$msg_group_id: $pw_gid' + '6' '$msg_member_of_groups: $pw_member_groups' + '7' '$msg_login_class: $pw_class' + '8' '$msg_password_expires_on: $pw_password_expires_on' + '9' '$msg_account_expires_on: $pw_account_expires_on' + 'A' '$msg_home_directory: $pw_home_dir' + 'B' '$msg_shell: $pw_shell' + " # END-QUOTE + esac + + case "$mode" in + Add|Edit/View) + if [ -d "$pw_home_dir" ]; then menu_items="$menu_items + '-' '$msg_create_home_directory: $msg_n_a' + 'D' '$msg_create_dotfiles: $pw_dotfiles_create' + "; else menu_items="$menu_items + 'C' '$msg_create_home_directory: $pw_home_create' + 'D' '$msg_create_dotfiles: $pw_dotfiles_create' + "; fi + ;; + Delete) + if [ -d "$pw_home_dir" ]; then menu_items="$menu_items + 'C' '$msg_delete_primary_group: $pw_group_delete' + 'D' '$msg_delete_home_directory: $pw_home_delete' + "; else menu_items="$menu_items + 'C' '$msg_delete_primary_group: $pw_group_delete' + '-' '$msg_delete_home_directory: $msg_n_a' + "; fi + ;; + esac + + size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$menu_text\" \ + \"\$hline\" \ + $menu_items ) + + eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$menu_text\" $size \ + $menu_items \ + 2> $DIALOG_TMPDIR/dialog.menu.$$ + + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + # Exit if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || f_die + + case "$mtag" in + X) # Exit + if [ "$save_flag" ]; then + save_changes || continue + fi + break + ;; + 1) # Login + case "$mode" in + Add) f_dialog_input_name "$pw_name" ;; + Edit/View|Delete) + f_dialog_menu_user_list + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + # Loop if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || continue + + [ "$mtag" = "X $msg_exit" ] && continue + + user="$mtag" + f_input_user "$user" || f_die 1 "$msg_login_not_found" + cur_pw_name="$pw_name" + cur_pw_password="$pw_password" + cur_pw_uid="$pw_uid" + cur_pw_gid="$pw_gid" + cur_pw_member_groups="$pw_member_groups" + cur_pw_class="$pw_class" + cur_pw_password_expire="$pw_password_expire" + cur_pw_account_expire="$pw_account_expire" + cur_pw_gecos="$pw_gecos" + cur_pw_home_dir="$pw_home_dir" + cur_pw_shell="$pw_shell" + cur_pw_group_delete="$pw_group_delete" + cur_pw_home_create="$pw_home_create" + cur_pw_home_delete="$pw_home_delete" + cur_pw_dotfiles_create="$pw_dotfiles_create" + [ "$mode" != "Delete" ] && save_flag= + esac + ;; + 2) # Full Name + f_dialog_input_gecos "$pw_gecos" + ;; + 3) # Password + f_dialog_input_password + ;; + 4) # UID + f_dialog_input_uid "$pw_uid" + ;; + 5) # Default Group + f_dialog_input_gid "$pw_gid" + ;; + 6) # Member of Groups + f_dialog_input_member_groups "$pw_member_groups" + ;; + 7) # Login Class + f_dialog_input_class "$pw_class" + ;; + 8) # Password Expire on + f_dialog_input_change "$pw_password_expire" + ;; + 9) # Account Expire on + f_dialog_input_expire "$pw_account_expire" + ;; + A) # Home Directory + f_dialog_input_home_dir "$pw_home_dir" + ;; + B) # Shell + f_dialog_input_shell "$pw_shell" + ;; + esac + + case "$mode" in + Delete) + case "$mtag" in + C) # Delete Primary Group + f_dialog_input_group_delete ;; + D) # Delete Home Directory + f_dialog_input_home_delete ;; + esac + ;; + Add|Edit/View) + case "$mtag" in + C) # Create Home Directory + f_dialog_input_home_create + [ "$pw_home_create" = "$msg_no" ] && + pw_dotfiles_create="$msg_no" + ;; + D) # Create Dotfiles + f_dialog_input_dotfiles_create + [ "$pw_dotfiles_create" = "$msg_yes" ] && + pw_home_create="$msg_yes" + ;; + esac + ;; + esac + +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/usermgmt b/usr.sbin/bsdconfig/usermgmt/usermgmt new file mode 100755 index 0000000..460f46b --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/usermgmt @@ -0,0 +1,150 @@ +#!/bin/sh +#- +# Copyright (c) 2012 Ron McDowell +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +. $BSDCFG_LIBE/include/common.subr || exit 1 +f_include $BSDCFG_LIBE/include/dialog.subr +f_include $BSDCFG_LIBE/include/mustberoot.subr + +APP_DIR="070.usermgmt" +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local menu_list size + local hline="$hline_arrows_tab_enter" + + menu_list=" + 'X' '$msg_exit' + '1' '$msg_add_login' + '2' '$msg_edit_login' + '3' '$msg_delete_login' + '-' '-' + '4' '$msg_add_group' + '5' '$msg_edit_group' + '6' '$msg_delete_group' + " # END-QUOTE + + size=$( eval f_dialog_menu_size \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\" \ + \"\$hline\" \ + $menu_list ) + + eval $DIALOG \ + --clear --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\" $size $menu_list \ + 2> "$DIALOG_TMPDIR/dialog.menu.$$" +} + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts hSX flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Initialize +# +f_dialog_init +f_dialog_title "$msg_login_management" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init + +# +# Launch application main menu +# +while :; do + dialog_menu_main + retval=$? + mtag=$( f_dialog_menutag ) + f_dprintf "retval=$retval mtag=[$mtag]" + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + X) # Exit + exit 0 + ;; + + 1) # Add User + $BSDCFG_LIBE/$APP_DIR/useradd ${USE_XDIALOG:+-X} + ;; + + 2) # Edit/View User + $BSDCFG_LIBE/$APP_DIR/useredit ${USE_XDIALOG:+-X} + ;; + + 3) # Delete User + $BSDCFG_LIBE/$APP_DIR/userdel ${USE_XDIALOG:+-X} + ;; + + 4) # Add Group + $BSDCFG_LIBE/$APP_DIR/groupadd ${USE_XDIALOG:+-X} + ;; + + 5) # Edit/View Group + $BSDCFG_LIBE/$APP_DIR/groupedit ${USE_XDIALOG:+-X} + ;; + + 6) # Delete Group + $BSDCFG_LIBE/$APP_DIR/groupdel ${USE_XDIALOG:+-X} + ;; + + esac +done + +################################################################################ +# END +################################################################################ |