687 lines
16 KiB
Bash
Executable File
687 lines
16 KiB
Bash
Executable File
#!/bin/sh
|
|
# $Id: adduser,v 1.3 2002/07/16 22:24:53 tom Exp $
|
|
|
|
#
|
|
# Written by: Mike Glover, March 1997
|
|
# E-mail : vexus@home.com, glover@credit.erin.utoronto.ca
|
|
#
|
|
# Purpose:
|
|
# This is a graphical adduser program. The widgets are
|
|
# the CDK command line widgets provided by the CDK
|
|
# distribution. If you have any questions about CDK,
|
|
# or the command line widgets please feel free to mail
|
|
# me at one of the two above addresses.
|
|
#
|
|
|
|
#
|
|
# Copyright 2000, Mike Glover
|
|
# 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.
|
|
# 3. All advertising materials mentioning features or use of this software
|
|
# must display the following acknowledgment:
|
|
# This product includes software developed by Mike Glover
|
|
# and contributors.
|
|
# 4. Neither the name of Mike Glover nor the names of contributors
|
|
# may be used to endorse or promote products derived from this software
|
|
# without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY MIKE GLOVER 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 MIKE GLOVER 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.
|
|
#
|
|
|
|
#
|
|
# Set the screen and widget colors.
|
|
#
|
|
CDK_WIDGET_COLOR="</5>"; export CDK_WIDGET_COLOR
|
|
CDK_SCREEN_COLOR="</1>"; export CDK_SCREEN_COLOR
|
|
|
|
#
|
|
# Set up some variables.
|
|
#
|
|
CDK_DIALOG="../cdkdialog"
|
|
CDK_ENTRY="../cdkentry"
|
|
CDK_SCROLL="../cdkscroll"
|
|
tmpFile="/tmp/tmp.$$"
|
|
tmpInfo="/tmp/adduserInfo.$$"
|
|
shellFile="/tmp/shells.$$"
|
|
ACCOUNT_SHELL=""
|
|
ACCOUNT_INFO=""
|
|
ACCOUNT_NAME=""
|
|
ACCOUNT_HOME=""
|
|
ACCOUNT_GID=""
|
|
ACCOUNT_UID=""
|
|
GROUP_NAME=""
|
|
CURRENT_FUNCTION=1;
|
|
|
|
#
|
|
# This quits the program.
|
|
#
|
|
quitProgram()
|
|
{
|
|
#
|
|
# The person has decided to quit.
|
|
#
|
|
buttons="< OK >"
|
|
message="<C></B><#HL(30)>
|
|
<C></B>Add New User Canceled
|
|
<C></B>Program exiting
|
|
<C></B><#HL(30)>"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" -N 2> /dev/null
|
|
exit;
|
|
}
|
|
|
|
#
|
|
# This warns the user to what is about to happen. It
|
|
# gives them a safe 'out'
|
|
#
|
|
warnUser()
|
|
{
|
|
#
|
|
# Pop up a little message telling the user what is
|
|
# about to happen.
|
|
#
|
|
message="<C></B>Adding New User
|
|
|
|
You are about to add a new user. If you do not want to
|
|
do this, move the cursor to the cancel button and hit
|
|
return. This will exit this program. Otherwise hit
|
|
return to continue."
|
|
buttons="< OK >
|
|
< Cancel >"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
if [ $? -ne 0 ]; then
|
|
quitProgram;
|
|
fi
|
|
}
|
|
|
|
#
|
|
# This gets the account name from the user.
|
|
#
|
|
getAccountName()
|
|
{
|
|
#
|
|
# Keep doing this until we hit an account which does not
|
|
# already exist.
|
|
#
|
|
count=1;
|
|
while [ $count -ne 0 ]; do
|
|
#
|
|
# Get the account name from the user.
|
|
#
|
|
buttons="Next
|
|
Cancel"
|
|
label="</24/B>Account Name: "
|
|
title="<C></B>Account Name
|
|
|
|
<C>The name is the identity of the account which the
|
|
<C>user will use to access the system.
|
|
|
|
"
|
|
|
|
${CDK_ENTRY} -i "${ACCOUNT_NAME}" -f 15 -m 3 -F "</56/B>_" -T "${title}" -L "${label}" -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_NAME=`cat ${tmpFile}`
|
|
|
|
#
|
|
# Check the selected button.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
|
|
#
|
|
# Look for the account name in the password file.
|
|
#
|
|
count=`grep -c "^${ACCOUNT_NAME}" /etc/passwd`
|
|
if [ ${count} -eq 1 ]; then
|
|
buttons="< OK >"
|
|
message="<C></B>Account Found
|
|
|
|
<C>The account you provided
|
|
<C></B>${ACCOUNT_NAME}
|
|
<C>already exists in the password file. Please pick
|
|
<C>another account name."
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
fi
|
|
done
|
|
}
|
|
|
|
#
|
|
# This gets the account information.
|
|
#
|
|
getAccountInfo()
|
|
{
|
|
#
|
|
# Set up the entry field.
|
|
#
|
|
buttons="Next
|
|
Previous
|
|
Cancel"
|
|
label="</24/B>Personal Info: "
|
|
title="<C></B>Account Information.
|
|
|
|
Enter in </B>${ACCOUNT_NAME}<!B>'s personal information. This is usually the
|
|
account holders name, phone number, or extension. This is fairly freeform.
|
|
The only character you can not use is a colon (:). If you do all colons will
|
|
be stripped out by this process.
|
|
|
|
"
|
|
${CDK_ENTRY} -f 40 -i "${ACCOUNT_INFO}" -F "</56/B>_" -T "${title}" -L "${label}" -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_INFO=`cat ${tmpFile} | tr ':' ' '`
|
|
|
|
#
|
|
# Check the selected button.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
elif [ $selected -eq 1 ]; then
|
|
DIRECTION=-1; export DIRECTION;
|
|
return;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
}
|
|
|
|
#
|
|
# This gets the account GID.
|
|
#
|
|
getAccountGID()
|
|
{
|
|
#
|
|
# Get the 'users' GID from /etc/group.
|
|
#
|
|
if [ "$ACCOUNT_GID" = "" ]; then
|
|
count=`grep -c "^users" /etc/group`
|
|
if [ $count -eq 0 ]; then
|
|
USER_GID="100";
|
|
else
|
|
USER_GID=`grep "^users" /etc/group | cut -d: -f3`
|
|
fi
|
|
else
|
|
USER_GID="$ACCOUNT_GID";
|
|
fi
|
|
|
|
#
|
|
# Keep doing this until we get a GID which exists.
|
|
#
|
|
count=0;
|
|
while [ $count -eq 0 ]; do
|
|
#
|
|
# Get the GID.
|
|
#
|
|
buttons="Next
|
|
Previous
|
|
Cancel"
|
|
label="</24/B>Account GID: "
|
|
title="<C></B>Account GID
|
|
|
|
The GID (Group IDentification) must be a number which already
|
|
exists in the /etc/group file. The default group </B>users<!B>
|
|
has been provided for you.
|
|
|
|
"
|
|
${CDK_ENTRY} -f 6 -m 1 -i "${USER_GID}" -F "</56/B>_" -T "${title}" -L "${label}" -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_GID=`cat ${tmpFile}`
|
|
|
|
#
|
|
# Check the selected button.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
elif [ $selected -eq 1 ]; then
|
|
DIRECTION=-1; export DIRECTION;
|
|
return;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
|
|
#
|
|
# Look for GID in the /etc/group
|
|
#
|
|
count=`grep -c ".*:.*:${ACCOUNT_GID}:" /etc/group`
|
|
if [ ${count} -eq 0 ]; then
|
|
buttons="< OK >"
|
|
message="<C></B>Error: No Such GID
|
|
|
|
<C>The GID you provided does not exist.
|
|
<C>Please pick a GID which does exist.
|
|
"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
if [ $? -ne 0 ]; then
|
|
quitProgram;
|
|
fi
|
|
else
|
|
#
|
|
# Get the group name for later.
|
|
#
|
|
GROUP_NAME=`grep ".*:.*:${ACCOUNT_GID}:" /etc/group | cut -d: -f1`
|
|
fi
|
|
done
|
|
}
|
|
|
|
#
|
|
# This gets the account UID.
|
|
#
|
|
getAccountUID()
|
|
{
|
|
#
|
|
# Try to find the next available UID.
|
|
#
|
|
if [ "$ACCOUNT_UID" = "" ]; then
|
|
nextUID=`awk 'BEGIN {FS=":"} {print $3}' /etc/passwd | sort -n | grep -v "65535" | tail -1`
|
|
nextUID=`expr $nextUID + 1`
|
|
else
|
|
nextUID="$ACCOUNT_UID"
|
|
fi
|
|
|
|
#
|
|
# Keep doing this until we get a UID which does not exist.
|
|
#
|
|
count=1;
|
|
while [ $count -ne 0 ]; do
|
|
#
|
|
# Get the UID.
|
|
#
|
|
buttons="Next
|
|
Previous
|
|
Cancel"
|
|
label="</24/B>Account UID: "
|
|
title="<C></B>Account UID
|
|
|
|
The UID (User IDentification) must be a number which does not
|
|
already exist in the /etc/passwd file. The value filled in is
|
|
the next available UID found from the password file.
|
|
|
|
"
|
|
${CDK_ENTRY} -f 6 -i "${nextUID}" -m 1 -F "</56/B>_" -T "${title}" -L "${label}" -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_UID=`cat ${tmpFile}`
|
|
|
|
#
|
|
# Check the selected button.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
elif [ $selected -eq 1 ]; then
|
|
DIRECTION=-1; export DIRECTION;
|
|
return;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
|
|
#
|
|
# Look for UID in the /etc/passwd
|
|
#
|
|
count=`grep -c ".*:.*:${ACCOUNT_UID}:" /etc/passwd`
|
|
if [ ${count} -ne 0 ]; then
|
|
owner=`grep ".*:.*:${ACCOUNT_UID}:" /etc/passwd | head -1 |cut -d: -f1`
|
|
buttons="< OK >"
|
|
message="<C></B>Error: Duplicate UID
|
|
|
|
<C>The UID you provided is already owned by
|
|
<C>the account </B>$owner<!B>. Please pick a
|
|
<C>UID which does not already exist.
|
|
"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
if [ $? -ne 0 ]; then
|
|
quitProgram;
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
#
|
|
# This gets the account home directory.
|
|
#
|
|
getAccountHome()
|
|
{
|
|
if [ "${ACCOUNT_HOME}" = "" ]; then
|
|
defaultHome="/home/${ACCOUNT_NAME}"
|
|
else
|
|
defaultHome="${ACCOUNT_HOME}"
|
|
fi
|
|
|
|
#
|
|
# Set up the entry field.
|
|
#
|
|
buttons="Next
|
|
Previous
|
|
Cancel"
|
|
label="</24/B>Home Directory: "
|
|
title="<C></B>Account Home Directory.
|
|
|
|
Enter in the account's home directory. If the directory
|
|
does not currently exist, it will be created in the account
|
|
creation phase of this process. A reasonable default value
|
|
for the home directory has been provided.
|
|
|
|
"
|
|
${CDK_ENTRY} -f 20 -F "</56/B>_" -i "${defaultHome}" -T "${title}" -L "${label}" -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_HOME=`cat ${tmpFile}`
|
|
|
|
#
|
|
# Check the selected button.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
elif [ $selected -eq 1 ]; then
|
|
DIRECTION=-1; export DIRECTION;
|
|
return;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
}
|
|
|
|
#
|
|
# This gets the shell the user want to assign to
|
|
# the account.
|
|
#
|
|
getAccountShell()
|
|
{
|
|
count=0;
|
|
|
|
while [ "$count" -eq 0 ]; do
|
|
#
|
|
# Get the shell they want to use.
|
|
#
|
|
buttons="Next
|
|
Previous
|
|
Cancel"
|
|
title="<C>Account Shell
|
|
|
|
Pick one of the shells to use. If you want to use a
|
|
custom shell, pick </B>Custom<!B> and you will be
|
|
prompted for it's path.
|
|
"
|
|
echo "Custom" > ${shellFile}
|
|
cat /etc/shells >> ${shellFile}
|
|
${CDK_SCROLL} -H 5 -W 10 -T "${title}" -f ${shellFile} -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_SHELL=`cat ${tmpFile}`
|
|
|
|
#
|
|
# Check the selected buttons.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
count=1;
|
|
elif [ $selected -eq 1 ]; then
|
|
DIRECTION=-1; export DIRECTION;
|
|
return;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
|
|
#
|
|
# Check the answer.
|
|
#
|
|
if [ "$ACCOUNT_SHELL" = "Custom" ]; then
|
|
#
|
|
# Get the shell from the user.
|
|
#
|
|
buttons="Next
|
|
Previuous
|
|
Cancel"
|
|
label="</24/B>Shell Pathname: "
|
|
title="<C></B>Custom Account Shell
|
|
|
|
Enter in the path to the custom shell. The authenticity
|
|
of the shell will not be checked here. It is assumed that
|
|
the shell will exist when the account is ready to be used.
|
|
|
|
"
|
|
${CDK_ENTRY} -f 20 -F "</56/B>_" -T "${title}" -L "${label}" -B "${buttons}" 2> ${tmpFile}
|
|
selected=$?
|
|
ACCOUNT_SHELL=`cat ${tmpFile}`
|
|
|
|
#
|
|
# Check the selected buttons.
|
|
#
|
|
if [ $selected -eq 0 ]; then
|
|
DIRECTION=1; export DIRECTION;
|
|
count=1;
|
|
elif [ $selected -eq 1 ]; then
|
|
count=0;
|
|
else
|
|
quitProgram;
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
#
|
|
# This confirms the new account information.
|
|
#
|
|
confirmAccount()
|
|
{
|
|
message="<C></B>Confirm New Account.
|
|
You are about to add an account with the following
|
|
information:
|
|
|
|
<C><#HL(30)>
|
|
Account Name : </B>$ACCOUNT_NAME
|
|
Account Info : </B>$ACCOUNT_INFO
|
|
Account Home : </B>$ACCOUNT_HOME
|
|
Account Shell: </B>$ACCOUNT_SHELL
|
|
Account UID : </B>$ACCOUNT_UID
|
|
Account GID : </B>$ACCOUNT_GID
|
|
<C><#HL(30)>
|
|
|
|
Are you sure you want to do this. Hit </R>Yes<!R> if you
|
|
want to add the account; hit </R>No<!R> if you want to
|
|
edit the information; hit </R>Cancel<!R> if you want to
|
|
abandon all information.
|
|
"
|
|
buttons="< Yes >
|
|
< No >
|
|
< Cancel >"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
answer=$?
|
|
|
|
#
|
|
# Check the answer.
|
|
#
|
|
if [ "$answer" -eq 2 -o "$answer" -eq 255 ]; then
|
|
quitProgram;
|
|
fi
|
|
if [ "$answer" -eq 0 ]; then
|
|
confirm=1; export confirm;
|
|
else
|
|
confirm=0; export confirm;
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Find out if the user wants to change the password
|
|
# or not.
|
|
#
|
|
changeAccountPassword()
|
|
{
|
|
buttons="< Yes >
|
|
< No >"
|
|
message="<C></B>Change Account Password Now
|
|
|
|
Since the account was added without a password, this account
|
|
can be logged in to without providing a password. Would you
|
|
like to change the account's password now?
|
|
"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
answer=$?
|
|
if [ "$answer" -eq 0 ]; then
|
|
passwd $ACCOUNT_NAME
|
|
fi
|
|
}
|
|
|
|
#
|
|
# This verifies the users ability to modify the
|
|
# password file.
|
|
#
|
|
checkPermissions()
|
|
{
|
|
#
|
|
# Try to touch the passwd file.
|
|
#
|
|
touch /etc/passwd >/dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
#
|
|
# Can't touch the password file. Let's tell them and go.
|
|
#
|
|
buttons="< Log Into Root Now >
|
|
< Exit >"
|
|
message="<C></B>Can Not Edit Password File
|
|
|
|
It appears that you do not have permission to edit the
|
|
password file. To add a new user to this machine you
|
|
must be logged in as root. Would you like to su to root
|
|
now or exit and log in. If you try to su now, this
|
|
program will be restarted.
|
|
"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|
|
if [ $? -eq 0 ]; then
|
|
su root -c "$0"
|
|
fi
|
|
exit;
|
|
fi
|
|
}
|
|
|
|
#
|
|
# This creates the account and copies all needed
|
|
# information.
|
|
#
|
|
createAccount()
|
|
{
|
|
if [ ! -d "$ACCOUNT_HOME" ]; then
|
|
mkdir $ACCOUNT_HOME
|
|
fi
|
|
if [ "$ACCOUNT_SHELL" = "/bin/sh" ]; then
|
|
cp /etc/profile ${ACCOUNT_HOME}/.profile
|
|
fi
|
|
if [ "$ACCOUNT_SHELL" = "/bin/bash" ]; then
|
|
cp /etc/profile ${ACCOUNT_HOME}/.profile
|
|
fi
|
|
if [ "$ACCOUNT_SHELL" = "/bin/csh" ]; then
|
|
cp /etc/csh.cshrc ${ACCOUNT_HOME}/.cshrc
|
|
cp /etc/csh.login ${ACCOUNT_HOME}/.login
|
|
fi
|
|
if [ "$ACCOUNT_SHELL" = "/bin/tcsh" ]; then
|
|
cp /etc/csh.cshrc ${ACCOUNT_HOME}/.cshrc
|
|
cp /etc/csh.login ${ACCOUNT_HOME}/.login
|
|
fi
|
|
chown -R ${ACCOUNT_NAME}.${GROUP_NAME} $ACCOUNT_HOME
|
|
}
|
|
|
|
###########################################################
|
|
#
|
|
# This is the start of the info retrieval.
|
|
#
|
|
###########################################################
|
|
|
|
#
|
|
# Set up the intermiediate functions so we can go
|
|
# backward and forward.
|
|
#
|
|
function1()
|
|
{
|
|
getAccountName;
|
|
}
|
|
function2()
|
|
{
|
|
getAccountInfo;
|
|
}
|
|
function3()
|
|
{
|
|
getAccountGID;
|
|
}
|
|
function4()
|
|
{
|
|
getAccountUID;
|
|
}
|
|
function5()
|
|
{
|
|
getAccountHome;
|
|
}
|
|
function6()
|
|
{
|
|
getAccountShell;
|
|
}
|
|
function7()
|
|
{
|
|
confirmAccount;
|
|
}
|
|
|
|
#
|
|
# Make sure the user has permission to edit the password file.
|
|
#
|
|
checkPermissions;
|
|
|
|
#
|
|
# Tell the user what they are about to do.
|
|
#
|
|
warnUser;
|
|
|
|
#
|
|
# Call the functions to get the needed info.
|
|
#
|
|
confirm=0;
|
|
NUMBER=0;
|
|
DIRECTION=1;
|
|
while [ "$confirm" -eq 0 ]; do
|
|
NUMBER=`expr $NUMBER + $DIRECTION`
|
|
if [ $NUMBER -le 0 ]; then
|
|
NUMBER = 1;
|
|
fi
|
|
CURRENT_FUNCTION="function${NUMBER}";
|
|
$CURRENT_FUNCTION;
|
|
done
|
|
|
|
#
|
|
# Add the account to the password file.
|
|
#
|
|
cp /etc/passwd /etc/passwd.old
|
|
echo "${ACCOUNT_NAME}::${ACCOUNT_UID}:${ACCOUNT_GID}:${ACCOUNT_INFO}:${ACCOUNT_HOME}:${ACCOUNT_SHELL}" >> /etc/passwd
|
|
|
|
#
|
|
# Find out if the user wants to change the password or not.
|
|
#
|
|
changeAccountPassword;
|
|
|
|
#
|
|
# Create the account and copy . files.
|
|
#
|
|
createAccount;
|
|
|
|
#
|
|
# Pop up a last little message and tell the user everything
|
|
# if OK.
|
|
#
|
|
buttons="< OK >"
|
|
message="<C></B>Account Add Complete
|
|
|
|
The account </B>${ACCOUNT_NAME}<!B> has been added to the password
|
|
file. You should be able to log in under this account
|
|
now.
|
|
"
|
|
${CDK_DIALOG} -m "${message}" -B "${buttons}" 2> /dev/null
|