#!/bin/bash
# adduser - build a useradd string and a password for passwd
# by typedeaF
# grep -v '^#' thisfile.sh | less to strip the comments
# Make a semi-random password using an array of user-friendly characters
function mkpass() {
PASS=""
PASSLEN=8
array1=( q w e r t y u i o p a s d f g h j k l z x c v b n m
Q W E R T Y U I O P A S D F G H J K L Z X C V B N M
1 2 3 4 5 6 7 8 9 0 \! \@ \# \$ \% \^ \& \* \( \)
)
MODNUM=${#array1[*]}
count=0
while [ ${count:=0} -lt $PASSLEN ]
do
number=$(($RANDOM%$MODNUM))
PASS="$PASS""${array1[$number]}"
((count++))
done
echo $PASS
}
# center the text on the screen by finding the horizontal center with max_lines
# max_lines divided by two becomes the center line(aka. line_num)
# use the max lenght of the line divided in half to find the center column
# subtract half the output string from the center to create the offset to indent
function center_txt() {
PROMPT="$1"
str_len=${#PROMPT}
indent=$(( ((max_cols / 2)) - ((str_len / 2)) ))
line_num=$(( max_lines / 2 ))
tput cup ${line_num} ${indent}
echo "$PROMPT"
}
# indent_txt is intended to be used AFTER center_txt
# indent_txt just prints on the current line and centers the text horizontally
# line_num is global, so main keeps track of incrementing it
function indent_txt() {
PROMPT="$1"
str_len=${#PROMPT}
indent=$(( ((max_cols / 2)) - ((str_len / 2)) ))
tput cup ${line_num} ${indent}
echo "$PROMPT"
}
# mk_prompt creates an input prompt for the the read function
# 'read -p "==> " variable' would work, but I like this better
function mk_prompt() {
((line_num+=2))
tput cup $line_num 15
PROMPT="==> "
echo -n "${blink}${PROMPT}"
echo -n ${offblink}
}
# This function gathers all the information needed to generate the useradd string
function mkuser() {
USERNAME=""
FULLNAME=""
EXPIRE=""
GROUP=""
HOME=""
echo ${term_clr}
PROMPT="Enter the new Login account name"
center_txt "$PROMPT"
((line_num++))
PROMPT="(ex. typedeaf)"
indent_txt "$PROMPT"
mk_prompt
read USERNAME
echo ${term_clr}
PROMPT="Enter the users Full Name"
center_txt "$PROMPT"
((line_num++))
PROMPT="(ex. Mister typedeaF)"
indent_txt "$PROMPT"
mk_prompt
read FULLNAME
echo ${term_clr}
PROMPT="Select the users Primary Group"
center_txt "$PROMPT"
((line_num++))
PROMPT="(ex. type \"1\" for Primary Group staff)"
indent_txt "$PROMPT"
((line_num+=2))
indent=$(( ((max_cols / 2)) - 6 ))
tput cup $line_num $indent; ((line_num++)); echo "1) staff"
tput cup $line_num $indent; ((line_num++)); echo "2) faculty"
tput cup $line_num $indent; ((line_num++)); echo "3) parttime"
tput cup $line_num $indent; ((line_num++)); echo "4) adjunct"
mk_prompt
read REPLY
case "$REPLY" in
1)
GROUP="staff"
HOME="/home/$GROUP/$USERNAME"
# add some staff specific stuff here
;;
2)
GROUP="faculty"
HOME="/home/$GROUP/$USERNAME"
# add some faculty specific stuff here
;;
4)
GROUP="adjunct"
HOME="/home/$GROUP/$USERNAME"
# add some adjunct specific stuff here
;;
3)
GROUP="parttime"
HOME="/home/$GROUP/$USERNAME"
echo ${term_clr}
PROMPT="Enter the Expiration Date"
center_txt "$PROMPT"
((line_num++))
PROMPT="(ex. 2004-06-30 for June 30th 2004)"
indent_txt "$PROMPT"
mk_prompt
read EXPIRE
;;
* )
echo "Invalid choice"
;;
esac
}
# Just reset the terminal to normal
function _quit() {
reset -Q
echo "Exiting addfas.sh. Bye"
exit 0
}
# =================================================#
# Begin Main #
# =================================================#
# These are the tput commands used to terminal output formatting
term_clr=$(tput clear)
max_lines=$(tput lines)
max_cols=$(tput cols)
blink=$(tput blink)
offblink=$(tput sgr0)
let CONTINUE=0
# Set up a trap to handle control signals. If you start using temp files then
# this is where you would want to clean up.
trap _quit INT TERM QUIT
# This could just as easily been while [ TRUE ], but the CONTINUE sentinal
# is included for flexability.
while [ $CONTINUE -eq 0 ]
do
mkuser
echo ${term_clr}
PROMPT="User added with the following criteria"
center_txt "$PROMPT"
((line_num+=2))
# There are more complex ways to handle this, like with the tertiary expr?expr:expr
# syntax, but it only makes things more complex looking at the sake of saving a
# few key strokes. Notice that using something like ${EXPIRE+-e$EXPIRE}
# doesnt work quite like expected. Instead of trying to cut corners and make 'leet'
# code, just keep it simple.
if [ -z "$EXPIRE" ]; then
PROMPT="useradd -c\"$FULLNAME\" -d$HOME -g$GROUP $USERNAME"
indent_txt "$PROMPT"
((line_num+=2))
else
PROMPT="useradd -c\"$FULLNAME\" -d$HOME -e$EXPIRE -g$GROUP $USERNAME"
indent_txt "$PROMPT"
((line_num+=2))
fi
uline=$(tput smul)
offuline=$(tput rmul)
PROMPT="Recommended Password:"
# I confess, I couldn't find a way to get $PASSLEN to parse correctly so I gave up
# and used the variable constant '8'.
str_len=$(( ${#PROMPT} + 8 ))
indent=$(( ((max_cols / 2)) - ((str_len / 2)) ))
tput cup ${line_num} ${indent}
echo -n "${uline}$PROMPT${offuline} "
mkpass
tput cup $max_lines
# Here is where you might want to include your CONTINUE sentinal.
# Like: if [ "$REPLY" = "x" ]; then CONTINUE=1; fi
PROMPT="Press Return to continue. Press ^C to EXIT."
echo -n "${blink}${PROMPT}"
echo -n ${offblink}
read -s
done
# reset your signal traps
trap - INT TERM QUIT
exit 0
This script is more of a skeleton. The groups I included are just to give you an idea of how things might differ. In this script, parttime users have an expiration date set. Other things that would be common is changing their home directories, adding public_html directories, assigning various groups, adding particular paths to PATH, etc. Keep in mind that things ALL users should get assingned should be in the /etc/skel file.
This program plays it safe and just echos the useradd line, you can easily modify this to execute the command and check for a return status. Other things missing...well there is a total lack of input validation. If you take for granted that an admin should be using this, and that the examples are clear enough, then input validation should not be an issue. Input validation could be done by placing each read inside a loop and checking the $REPLY variable with expr $REPLY : '/some regex/'. Lastly, good UNIX programming practice stresses that critical information be written to stderr. You might consider altering each echo to redirect to stderr with the >&2 syntax.
If you haven't noticed, this program builds on the last article/script I published that generates random passwords. Read that article for information on how the password generation works. I use scripts like these all the time to help me generate long command line strings or for maintaining flat database files. This script makes good use of many of the advanced features of bash scripting.
Since bash will treat almost all variables as globals, it is important to initilize variables back to NULL or 0 at the begining of each iteration. You dont want your counters starting off at non zero numbers, etc.
Sorry for the lack of documentation. Using help bash_command or man bash is a good place to start if you are lost on something.
tF
|