1 #!/bin/bash
  2 #
  3 # @(#) Create a new user in OSX. V1.1
  4 #
  5 # xaos@xm5design.com - July 14, 2010
  6 #
  7 DSCLLIST="/tmp/dsclist.txt"
  8 DSCLLISTS="/tmp/dsclists.txt"
  9 DRURUN=0
 10 NUSER="newuser"
 11 FIND_NEXT_UID=0
 12 #
 13 #
 14 usage() {
 15     echo "Usage: $0 [ -l [user] | -h | -a | -d ] User_Name { UID | . } GID"
 16     echo -e "\nWhere:\n"
 17     echo -e "\t-a\t\tWill create the user as an administrator"
 18     echo -e "\t-d\t\tWill do a \"Dry Run\". It will check everything but not run any commands"
 19     echo -e "\t-h\t\tWill print this help message"
 20     echo -e "\t-l [user]\tWill list a user or all users and quit"
 21     echo -e "\nSpecifying a \".\" (dot) for a UID means find the next available one."
 22     echo -e "If the GID does not exist, the necessary commands to create it will be printed out." 
 23     echo -e "A default password (made of random numbers) will be created along with the userid."
 24 }
 25
 26 #
 27 # This only works for Darwin
 28     if [[ "$(uname -s)" != "Darwin" ]]
 29     then
 30         echo "This script will only work for OSX"
 31         exit 1
 32     fi
 33 #
 34 #
 35     NUSER=$1
 36     NUID=$2
 37     NGID=$3
 38     NADMIN=0
 39 #
 40 # Get help ?
 41     if [[ "${NUSER}" = "-h"* ||  "${NUSER}" = "--h"* ]]
 42     then
 43         usage
 44         exit 1
 45     fi
 46 #
 47 # Show a list of users?
 48     if [[ "${NUSER}" = "-l" ]]
 49     then
 50         shift
 51         MUSER=$1
 52         if [[ "${MUSER}" == "" ]]
 53         then
 54             GENULIST=$(dscl "." list /users | sort -k 1)
 55         else
 56             GENULIST=${MUSER}
 57         fi
 58         #
 59         DSCGLIST=$(dscl . list /Groups)
 60         #
 61         for ii in ${GENULIST}
 62         do
 63             echo "${ii}"
 64             dscl . read /Users/${ii} | egrep "PrimaryGroupID|NFSHomeDirectory|RealName|UniqueID|UserShell" >${DSCLLIST}
 65             while read line
 66             do
 67                 if [[ "${line}" = *PrimaryGroupID* ]]
 68                 then
 69                     set $line
 70                     gtext=$1;gnumid=$2
 71                     foundid=0
 72                     #
 73                     for kk in ${DSCGLIST}
 74                     do
 75                         GIDTEXT=$(dscl . read /Groups/$kk | grep PrimaryGroupID)
 76                         set $GIDTEXT
 77                         gtextg=$1; gnumidg=$2
 78                         #
 79                         # now, compare the two
 80                         if (( gnumid == gnumidg ))
 81                         then
 82                             foundid=1
 83                             foundname=$kk
 84                             break
 85                         fi
 86                     done
 87                     if (( foundid ))
 88                     then
 89                         echo -e "\tPrimaryGroupID:\n\t\tName   : ${foundname}\n\t\tNumber : ${gnumid}\n\t\tExists : Yes"
 90                     else
 91                         echo -e "\tPrimaryGroupID:\n\t\tName   : ${foundname}\n\t\tNumber : ${gnumid}\n\t\tExists : No"
 92                     fi
 93                 else
 94                     set $line
 95                     key=$1
 96                     shift
 97                     keytext=$*
 98                     echo -e "\t${key}\n\t\t\"${keytext}\""
 99                 fi
100             done < ${DSCLLIST}
101         done
102         rm -f ${DSCLLIST}
103         exit 0
104     fi
105 #
106 # Does he need to be admin or dry run?
107     while :
108     do
109         if [[ "${NUSER}" = "-"* ]]
110         then
111             if [[ "${NUSER}" = "-a" ]]
112             then
113                 NADMIN=1
114             elif [[ "${NUSER}" = "-d" ]]
115             then
116                 DRYRUN=1
117             else
118                 echo "Error: Unknown option: \"${NUSER}\". Bye."
119                 exit
120             fi
121             shift
122             NUSER=$1
123             NUID=$2
124             NGID=$3
125         else
126             break
127         fi
128     done
129 #
130 # Check for no parms
131     if [[ "${NGID}" = "" ]]
132     then
133         usage
134         exit 1
135     fi
136 #
137 # Check if the user exists
138     if dscl "." read /Users/${NUSER} >/dev/null 2>&1
139     then
140         echo -e "User: \"${NUSER}\",  already exists. Bye."
141         exit 1
142     fi
143 #
144 #
145 if [[ "${NUID}" = "." ]]
146 then
147     FIND_NEXT_UID=1
148 fi
149
150 #
151 #
152 if (( FIND_NEXT_UID ))
153 then
154     #
155     # Go through every id
156         GENULIST=$(dscl "." list /Users | sort -k 1)
157         rm -rf ${DSCLLIST}
158         for ii in ${GENULIST}
159         do
160             dscl . read /Users/${ii} | egrep "UniqueID" >>${DSCLLIST}
161         done
162         cat ${DSCLLIST} | awk '{print $2}' | sort -n > ${DSCLLISTS}
163         vim  ${DSCLLISTS}
164         NUID=$(tail -1 ${DSCLLISTS})
165         let NUID=$NUID+1
166         echo -e "New UID found: \"${NUID}\""
167         rm -f ${DSCLLIST} ${DSCLLISTS}
168 fi
169 #
170 # Check if the UID exists
171     GENULIST=$(dscl "." list /Users | sort -k 1)
172     #
173     foundid=0
174     for ii in ${GENULIST}
175     do
176         dscl . read /Users/${ii} | egrep "UniqueID" >${DSCLLIST}
177         while read line
178         do
179             set $line
180             text=$1;numid=$2
181             if (( numid == NUID ))
182             then
183                 foundid=1
184                 break
185             fi
186         done < ${DSCLLIST}
187     done
188     rm -f ${DSCLLIST}
189     #
190     # Check it
191     if (( foundid ))
192     then
193         echo -e "UID: \"${NUID}\", already exists. Bye."
194         exit 1
195     else
196         echo -e "UID: \"${NUID}\", does not exist. Cool."
197     fi
198 #
199 # Check if the GID exists
200     GENULIST=$(dscl "." list /Groups | sort -k 1)
201     #
202     foundid=0
203     for ii in ${GENULIST}
204     do
205         dscl . read /Groups/${ii} | egrep "PrimaryGroupID" >${DSCLLIST}
206         while read line
207         do
208             set $line
209             text=$1;numid=$2
210             if (( numid == NGID ))
211             then
212                 foundid=1
213                 break
214             fi
215         done < ${DSCLLIST}
216     done
217     rm -f ${DSCLLIST}
218     #
219     # Check it
220     if (( foundid ))
221     then
222         echo -e "GID: \"${NGID}\", exists. Cool."
223     else
224         echo -e "GID: \"${NGID}\", does not exist.\n\tYou must create with commands:"
225         echo -e "\t\tdscl . create /Groups/${NUSER}"
226         echo -e "\t\tdscl . create /Groups/${NUSER} name ${NUSER}"
227         echo -e "\t\tdscl . create /Groups/${NUSER} passwd \"*\""
228         echo -e "\t\tdscl . create /Groups/${NUSER} gid ${NGID}"
229         echo -e "\t\tdscl . create /Groups/${NUSER} users  ${NUSER}"
230     fi
231 #
232 #
233     MYNAME="Dr. Maximvs ${NUSER}"
234     MYPASS=$(printf "%d\n" "${RANDOM}${RANDOM}${RANDOM}")
235 #
236     if (( DRYRUN ))
237     then
238         echo -e "Preparing New Account\n\tUser: \"${NUSER}\"\n\tName: \"${MYNAME}\"\n\tUID: \"${NUID}\"\n\tGID: \"${NGID}\"\n\tPassword: \"${MYPASS}\""
239         exit
240     fi
241 #
242 # Process request
243     dscl "." -create /Users/${NUSER} || exit 1
244
245     #
246     # Create and set the shell property to bash.
247     dscl "." -create /Users/${NUSER} UserShell /bin/bash || { echo "Error Creating User Shell. Account was never created"; exit 1; }
248
249     #
250     # Create and set the user’s full name.
251     dscl "." -create /Users/${NUSER} RealName "${MYNAME}" || { echo -e "Error Creating User Real Name. Account Will be deleted"; dscl . delete /Users/${NUSER}; exit 1; }
252
253     #
254     # Create and set the user’s ID.
255     dscl "." -create /Users/${NUSER} UniqueID ${NUID} || { echo -e "Error Creating UID. Account Will be deleted"; dscl . delete /Users/${NUSER}; exit 1; }
256
257     #
258     # Create and set the user’s group ID property.
259     dscl "." -create /Users/${NUSER} PrimaryGroupID ${NGID} || { echo -e "Error Creating GID. Account Will be deleted"; dscl . delete /Users/${NUSER}; exit 1; }
260
261     #
262     # Create and set the user home directory.
263     dscl "." -create /Users/${NUSER} NFSHomeDirectory /Users/${NUSER} || { echo -e "Error Creating Home Directory. Account Will be deleted"; dscl . delete /Users/${NUSER}; exit 1; }
264
265     #
266     # Set the password.
267     dscl "." passwd /Users/${NUSER} ${MYPASS} || { echo -e "\nError Creating User Password. Continuing"; dscl . delete /Users/${NUSER}; exit 1; }
268
269     echo -e "New User created.\n\tUser: \"${NUSER}\"\n\tName: \"${MYNAME}\"\n\tDUID: \"${NUID}\"\n\tGID: \"${NGID}\"\n\tPassword: \"${MYPASS}\""
270
271     if (( NADMIN ))
272     then
273         #
274         # If you would like Dr. Maximus to be able to perform administrative functions:
275         dscl "." -append /Groups/admin GroupMembership ${NUSER} || exit 1
276         echo -e "\tAdministrator: \"Yes\""
277     else
278         echo -e "\tAdministrator: \"No\""
279     fi
280     #
281     # Create the home dir
282         createhomedir -c > /dev/null || exit 1
283         chmod 700 /Users/${NUSER}
284     #
285     # Now, check with Dscl
286         echo "Now Checking with dscl:"
287         dscl . read /Users/${NUSER} | sed 's/^/   /'
288     #
289     echo -e "\nTo Delete the user do:\n\tdscl \".\" delete /Users/${NUSER}"
290 #
291 exit 0