USERMOD command written in bash 

#!/bin/bash
#Ver 1.3
#presmerovat chyb vystup dostderr
# -o
# -p -> prestehovat do shadow
# 


function find_uid_in_passwd
{
grep -v "^#"  $passwd_file |cut -d"#" -f1| while read line
do
CUR_UID=`echo $line |awk -F: '{print $3} '`
if [  $CUR_UID = $P_UID ]; then
echo $CUR_UID;
break;
fi
done


}

function group_to_number
{
 if [ ! -z `echo $G_T_N |grep -E '^[0-9]+$'` ]
 then
 echo $G_T_N
 else
    which_file=$group_file
    find_name=$G_T_N
    group_line=`find_user_in_file`
    group_result=`echo $group_line | awk -F: '{print $3}'`
    echo $group_result
 fi

}

function fill_entry_from_passwd
{
IFS_OLD=$IFS
export IFS=":"
set -- $line
name=$1
pass=$2
uid=$3
gid=$4
gecos=$5
home_dir=$6
shell=$7
#
#name=`echo $line |awk -F: '{print $1} '`
#pass=`echo $line |awk -F:  '{print $2}'`
#uid=` echo $line |awk -F:  '{print $3}'`
#gid=` echo $line |awk -F:  '{print $4}'`
#gecos=`echo $line|awk -F:  '{print $5}'`
#home_dir=`echo $line|awk -F: '{print $6}'`
#shell=`echo $line|awk -F: '{print $7}'`
IFS=$IFS_OLD
}

function fill_entry_from_shadow
{
IFS_OLD=$IFS
export IFS=":"
set -- $line
name=$1
pass=$2
d_last_p_change=$3
d_before_p_may_change=$4
d_after_p_must_change=$5
d_before_expire_warn=$6
d_after_expired_disabled=$7
d_disabled=$8
reserved=$9
#name=`echo $line |awk -F: '{print $1} '`
#pass=`echo $line |awk -F:  '{print $2}'`
#d_last_p_change=` echo $line |awk -F:  '{print $3}'`
#d_before_p_may_change=` echo $line |awk -F:  '{print $4}'`
#d_after_p_must_change=`echo $line|awk -F:  '{print $5}'`
#d_before_expire_warn=`echo $line|awk -F: '{print $6}'`
#d_after_expired_disabled=`echo $line|awk -F: '{print $7}'`
#d_disabled=`echo $line|awk -F: '{print $8}'`
#reserved=`echo $line|awk -F: '{print $9}'`
IFS=$IFS_OLD

}


function find_user_in_file
{

#cat $which_file |grep -v "^#"|cut -d"#" -f1| while read line
#do
#CUR_USER=`echo $line |awk -F: '{print $1} '`
#if [  $CUR_USER = $find_name ]; then
#echo $line;
#break;
#fi
#done
grep ^$find_name $which_file | cut -d"#" -f1
}

function find_user_in_passwd
{
which_file=$passwd_file
find_name=$P_LOGIN
find_user_in_file
}

function find_group_in_group
{
which_file=$group_file
find_name=$group_test
find_user_in_file
}

function find_user_in_shadow
{
which_file=$shadow_file
find_name=$P_LOGIN
find_user_in_file
}


function alter_line_passwd
{
line=$USER_LINE_PASSWD
fill_entry_from_passwd
    
    if [ -n "$P_COMMENT" ]; then
    gecos=$P_COMMENT
    fi    
    
    if [ -n "$P_COMMENT_EMPTY" ]; then
    gecos=
    fi   
     
    if [ -n "$P_HOMEDIR" ]; then
    home_dir=$P_HOMEDIR
    fi    
    if [ -n "$P_LOGIN_NAME" ]; then
    name=$P_LOGIN_NAME
    fi    
    if [ -n "$P_PASSWD" ]; then
    pass=$P_PASSWD
    fi    
    if [ -n "$P_SHELL" ]; then
    shell=$P_SHELL
    fi    
    if [ -n "$P_UID" ]; then
    uid_result=`find_uid_in_passwd`
      if [ -n "$uid_result" ]; then
	if [ -z "$P_OVERRIDE" ]; then
	dummy="uid"	
	fi
       fi
    uid=$P_UID
   #TODO set to rest of files
   
    fi    
    if [ -n "$P_INITIAL_GROUP" ]; then
    G_T_N=$P_INITIAL_GROUP
    gid=`group_to_number`
	if [ -z "gid" ]; then
	dummy="gid"	
	fi    
    #TODO test na existenci skupiny
    fi
if [ -z "$dummy" ]; then
    echo $name:$pass:$uid:$gid:$gecos:$home_dir:$shell
fi
}

function alter_line_shadow
{
line=$USER_LINE_SHADOW
fill_entry_from_shadow

    if [ -n "$P_LOGIN_NAME" ]; then
    name=$P_LOGIN_NAME
    fi    
    if [ -n "$P_INACTIVE_DAYS" ]; then
    d_after_expired_disabled=$P_INACTIVE_DAYS
    fi    
    if [ -n "$P_EXPIRE_DATE" ]; then
    
	if [ $P_EXPIRE_DATE = "0" ] 
        then
	d_disabled=
	else
	d_disabled=`date -d $P_EXPIRE_DATE +%s`
	fi 
    fi   
    
echo $name:$pass:$d_last_p_change:$d_before_p_may_change:$d_after_p_must_change:$d_before_expire_warn:$d_after_expired_disabled:$d_disabled:$reserved
}
function fill_entry_from_group
{
IFS_OLD=$IFS
export IFS=":"
set -- $line
group_name=$1
group_pass=$2
gid=$3
user_list=$4

#group_name=`echo $line |awk -F: '{print $1} '`
#group_pass=`echo $line |awk -F:  '{print $2}'`
#gid=` echo $line |awk -F:  '{print $3}'`
#user_list=` echo $line |awk -F:  '{print $4}'`
IFS=$IFS_OLD
}

function alter_file_group
{
#echo T6
#line=$USER_LINE_GROUP

#fill_entry_from_group
    if [ -n "$P_GROUP_SUPP" ]; then
	for group_test in `echo $P_GROUP_SUPP | sed 's/,/ /g'` 
	do
        find_result=`find_group_in_group`
	if [ -z "$find_result" ]; then
	echo "Warning non-exitent group:" $group_test
	fi
        done;
    fi
    if [ -n "$P_LOGIN_NAME" ]; then
    sed 's/\(.*:.*:.*\)'$P_LOGIN'\(.*\)/\1'$P_LOGIN_NAME'\2/' $group_file > /tmp/g$$roup_tmp  
    mv /tmp/g$$roup_tmp $group_file
    P_LOGIN=$P_LOGIN_NAME # MODIFIKACE globl USERA, posledni misto kde se to meni
    fi    
   

    if [ -n "$P_GROUP_SUPP" ]; then
    #echo T7
    grep_param=^`echo $P_GROUP_SUPP | sed 's/,/|^/g'` #konstrukce regul vyrazu 
    egrep -v $grep_param $group_file > /tmp/g$$roup.new_p1 #skupiny co nechci modifikovat, ale chci zmenit if NOT user
    #TODO:
    # vyhazet s groups.new usera (nema se tam v zadnym pripade uz vyskytovat)
    #
    group_to_change=`egrep  '.*:.*:.*:.*'$P_LOGIN'*' /tmp/g$$roup.new_p1` #radky z kterych musim vyhodit usera, neni nove clenem
    egrep  -v  '.*:.*:.*:.*'$P_LOGIN'*' /tmp/g$$roup.new_p1 > /tmp/g$$roup.new   #cisty
    rm -f /tmp/g$$roup.new_p1
    group_line_change=`egrep $grep_param $group_file|sort`  #skupiny co chci zmenit (radky)
    #group_list=`echo $P_GROUP_SUPP |tr , "\n" |sort` #seznam skupin
#echo T8
#echo $group_to_change
	for line in $group_to_change
	do
	fill_entry_from_group #naplni z $line do promenych
	new_user_list=
	  for users_to_change in `echo $user_list |tr , " " ` #skupina, kde odebereme
		do
		if [[ $P_LOGIN != $users_to_change ]]; then
 	       new_user_list=$new_user_list,$users_to_change
		fi
#	    echo $users_to_change
 
		done;
	echo $group_name:$group_pass:$gid:${new_user_list#,} >>/tmp/g$$roup.new
	done;	     

#    echo $group_list
#    echo $group_line_change
#	echo $group_list | while read line
#	do
# TODO: test jestli skupina existuje
#       + prejmenovani
#
# P_LOGIN
	for line in $group_line_change
	do
	fill_entry_from_group
	if [ -z `echo $user_list|grep $P_LOGIN` ] ; then
	#Todo jestli je PRVNI
	    if [ -z "$user_list" ]; then
	    echo $group_name:$group_pass:$gid:$P_LOGIN  >> /tmp/g$$roup.new #user je novy
	    else
	    echo $group_name:$group_pass:$gid:$user_list,$P_LOGIN  >> /tmp/g$$roup.new #user je novy
	    fi
	else
	echo $group_name:$group_pass:$gid:$user_list	>> /tmp/g$$roup.new #user uz tam je
	fi
	done;	     
#ODBLOKOVAT
	mv /tmp/g$$roup.new $group_file
    fi    
    

}

function print_help
{
	echo "usermod  [-c comment] [-d home_dir [ -m]]"
	echo "         [-e expire_date] [-f inactive_time]"
	echo "         [-g initial_group] [-G group[,...]]"
	echo "         [-l login_name] [-p passwd]"
	echo "         [-s shell] [-u uid [ -o]] login"
								    
}
# Program start:


passwd_file="passwd"
group_file="group"
shadow_file="shadow"
    if 	[ $# = 1 ]; then	
	print_help
	exit 255
    fi

while [ $# != 1 ]
    do
    case "$1" in
	'-c') #done
	P_COMMENT=$2
	if [ -n "$P_COMMENT" ] ;then P_COMMENT_EMPTY=TRUE
	fi 
	shift 2
    ;;
	'-d')
	P_HOMEDIR=$2
	shift 2
    ;;
	'-e')
	P_EXPIRE_DATE=$2
	shift 2
    ;;
	'-f')
	P_INACTIVE_DAYS=$2
	shift 2
    ;;
	'-g')
	P_INITIAL_GROUP=$2
	shift 2
    ;;
	'-G')
	P_GROUP_SUPP=$2
	shift 2
    ;;
	'-l')
	P_LOGIN_NAME=$2
	TEST_NAME=`grep "^"$P_LOGIN_NAME $passwd_file`
#	echo $passwd_file $P_LOGIN_NAME
	if [ -n "$TEST_NAME" ]; then
	    echo Existing username !
	    exit 9
	fi
	shift 2
    ;;
	'-p')
	P_PASSWD=$2
	shift 2
    ;;
	'-s')
	P_SHELL=$2
	shift 2
    ;;
	'-u')
	P_UID=$2
	shift 2
    ;;
	'-m')
	P_MOVE="YES"
	shift 1
    ;;
	'-o')
	P_OVERRIDE="YES"
	shift 1
    ;;
	*)
	print_help
	exit 255
    esac
done

    if 	[ $# = 1 ]; then	
	P_LOGIN=$1
    fi

USER_LINE_PASSWD=`find_user_in_passwd`

#echo T1

if [ -z "$USER_LINE_PASSWD" ]; then
echo No such user
exit 255;
fi

ALTERED_LINE_PASSWD=`alter_line_passwd`

#echo T2

if [ -z "$ALTERED_LINE_PASSWD" ]; then
    echo Duplicit uid found, use -o to override, or non existing group
    exit 255
fi

USER_LINE_SHADOW=`find_user_in_shadow`

#echo T3

if [ -z "$USER_LINE_SHADOW" ]; then
echo No such user in shadow file
exit 255;
fi
ALTERED_LINE_SHADOW=`alter_line_shadow`

#echo T4

alter_file_group

#echo ----------------------
#echo $USER_LINE_PASSWD
#echo $ALTERED_LINE_PASSWD
#echo ----------------------
#echo $USER_LINE_SHADOW
#echo $ALTERED_LINE_SHADOW
#echo ----------------------
#echo $USER_LINE_GROUP
#echo $ALTERED_LINE_GROUP
#echo ----------------------

cp $passwd_file $passwd_file""~
grep -v "$USER_LINE_PASSWD"  $passwd_file""~ >$passwd_file  ; echo $ALTERED_LINE_PASSWD >>$passwd_file   
cp $shadow_file $shadow_file""~
grep -v "$USER_LINE_SHADOW"  $shadow_file""~ >$shadow_file  ; echo $ALTERED_LINE_SHADOW >>$shadow_file   
cp $group_file $group_file""~
#mv group.new $group_file

if [ -n "$P_MOVE" ]; then
    if [ -n "$P_HOMEDIR" ]; then
	mv -R ~/$P_LOGIN/ $P_HOMEDIR 
    fi
fi