Skip to content

Instantly share code, notes, and snippets.

@kbanman
Created September 21, 2012 22:16
Show Gist options
  • Save kbanman/3764255 to your computer and use it in GitHub Desktop.
Save kbanman/3764255 to your computer and use it in GitHub Desktop.
adduser implementation for OSX
#!/usr/bin/env php
<?php
function prompt($msg, $default = false)
{
if ($default !== false)
{
$msg .= ' ['.$default.']';
}
echo $msg.': ';
$fh = fopen('php://stdin', 'r');
$input = fgets($fh);
fclose($fh);
if ($default !== false && (empty($input) || $input == "\n"))
{
return $default;
}
return trim($input);
}
function prompt_bool($msg, $default)
{
do
{
$input = strtolower(prompt($msg, $default));
$valid = in_array($input, array('y', 'n', 'yes', 'no'));
if ( ! $valid)
{
echo "Please enter either 'yes' or 'no'\n";
}
}
while ( ! $valid);
return in_array($input, array('y', 'yes'));
}
function get_shells()
{
if ( ! $fh = fopen('/etc/shells', 'r'))
{
throw new Exception('Error reading shells. Make sure you have read permissions on /etc/shells');
}
$shells = array();
while ($shell = fgets($fh))
{
$shell = trim($shell);
if ( empty($shell) || substr($shell, 0, 1) == '#')
{
continue;
}
$shells[substr($shell, strrpos($shell, '/')+1)] = trim($shell);
}
return $shells;
}
function get_groups()
{
$group_data = shell_exec('dscl . readall /Groups');
// @todo: This fails on records with linebreaks inside the value, for example:
/*
AppleMetaNodeLocation: /Local/Default
GeneratedUID: ABCDEFAB-CDEF-ABCD-EFAB-CDEF0000000A
Password: *
PrimaryGroupID: 10
RealName:
Creator Owner
RecordName:
owner
BUILTIN\Creator Owner
RecordType: dsRecTypeStandard:Groups
SMBSID: S-1-3-0
*/
$pattern = '/Password: (.*?)[\n\r]+PrimaryGroupID: (\d+)[\n\r]+RealName:\s+(.*)[\n\r]+RecordName:\s+(.*)[\n\r]+RecordType/';
preg_match_all($pattern, $group_data, $matches);
$groups = array();
foreach ($matches[0] as $i => $match)
{
//$passwd = trim($matches[1][$i]);
$gid = (int) $matches[2][$i];
//$name = trim($matches[3][$i]);
$group = trim($matches[4][$i]);
$groups[$gid] = $group;
}
return $groups;
}
function get_uid($uid = 500)
{
// We loop to find a numeric value which is not a users uniqueid or a groups
// primary group id starting at $uid
do
{
$uid++;
$user = shell_exec("dscl . search Users UniqueID $uid");
$group = shell_exec("dscl . search Groups PrimaryGroupID $uid");
}
while ( ! empty($user) || ! empty($group));
return $uid;
}
function user_exists($username)
{
$user = shell_exec("dscl . search Users RecordName $username");
return ! empty($user);
}
if (trim(shell_exec('whoami')) != 'root')
{
die("This script must be run as root.\n");
}
// Username
do
{
$username = prompt('Username');
if (user_exists($username))
{
echo "User exists!\n";
}
}
while (user_exists($username));
// Full name
$fullname = prompt('Full name');
// UID
$uid = prompt('Uid', get_uid());
// Login group
$groups = get_groups();
$group = prompt('Login group', $username);
if ($group_exists = isset($groups[$group]))
{
$group_name = $groups[$group];
}
else
{
echo "Will create new group '$group'\n";
$group_name = ucfirst($group);
}
// Login shell
$shells = get_shells();
$shell_names = array_keys($shells);
do
{
$shell = prompt('Shell ('.implode(' ', $shell_names).')', reset($shell_names));
}
while (empty($shells[$shell]));
$shell = $shells[$shell];
// Home directory
$home_dir = prompt('Home directory', '/Users/'.$username);
// Password
if ($use_password = prompt_bool('Use password-based authentication?', 'yes'))
{
do
{
$password = prompt('Enter password');
$confirm = prompt('Enter password again');
if ($password !== $confirm)
{
echo "Passwords did not match!\n";
}
}
while ($password !== $confirm);
}
else
{
$password = '*';
}
// Add to home screen?
$hide_user = ! prompt_bool('Add user to login screen?', 'no');
$create_user = <<<EOF
sudo dscl . create /Users/$username
sudo dscl . create /Users/$username UniqueID $uid
sudo dscl . create /Users/$username PrimaryGroupID $uid
sudo dscl . create /Users/$username NFSHomeDirectory $home_dir
sudo dscl . create /Users/$username Password '$password'
sudo dscl . create /Users/$username UserShell $shell
sudo dscl . create /Users/$username RealName '$fullname'
EOF;
echo passthru($create_user);
$create_group = <<<EOF
sudo dscl . create /Groups/$group
sudo dscl . create /Groups/$group PrimaryGroupID $uid
sudo dscl . create /Groups/$group RealName '$group_name'
EOF;
if ( ! $group_exists)
{
echo passthru($create_group);
}
$create_dir = <<<EOF
if [[ ! -d $home_dir ]] ; then
sudo mkdir $home_dir
fi
sudo chown -R $username:$group $home_dir
EOF;
passthru($create_dir);
if ($hide_user)
{
passthru("sudo defaults write /Library/Preferences/com.apple.loginwindow HiddenUsersList -array-add $username");
}
echo "All done\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment