All,
Here's a postinstall script I wrote in an hour or so to fill user home folders for PKG-style packages. It should work as-is, but I have a couple questions. Does anyone know which parameter passed to package scripts tells it where to install? And does anyone know of a way to get id to work properly from a different volume without using chroot?
Thanks.
#!/usr/bin/python
"""
This script clones anything it finds in /private/tmp/fillUsers to all existing
non-hidden users, as well as all user template localizations. It is meant to be
used as a postinstall script for packages that need this functionality,
mimicking the functionality available in JAMF's Casper Suite for DMG packages.
Note that it requires the jamf binary to be installed.
"""
import os, subprocess, sys
from xml.dom import minidom
fsroot = '/'
src = os.path.join(fsroot, '/private/tmp/fillUsers')
userList = subprocess.Popen(
[os.path.join(fsroot, '/usr/sbin/jamf'), 'listUsers'],
stdout = subprocess.PIPE,
).communicate()[0]
uids = minidom.parseString(userList).getElementsByTagName(u'id')
names = minidom.parseString(userList).getElementsByTagName(u'name')
homes = minidom.parseString(userList).getElementsByTagName(u'home')
uids = [node.firstChild.nodeValue for node in uids]
names = [node.firstChild.nodeValue for node in names]
homes = [node.firstChild.nodeValue for node in homes]
users = list(zip(uids, names, homes))
# kinda nice that uid 0 happens to have the right gid (0) for this
for lang in os.listdir(os.path.join(fsroot, '/System/Library/User Template')):
users.append((
'0',
'template (%s)' % (lang, ),
os.path.join('/System/Library/User Template/', lang),
))
for uid, name, home in users:
gid = subprocess.Popen(
['/usr/bin/id', '-g', uid],
stdout = subprocess.PIPE
).communicate()[0] # if fsroot != '/', id won't find the right user
print "Filling %s for user %s" % (home, name)
subprocess.check_call(['/usr/sbin/chown', '-R', uid + ':' + gid, src])
subprocess.check_call(['/usr/bin/ditto', src, os.path.join(fsroot, home)])
print "Cleaning up %s" % (src, )
subprocess.check_call(['/bin/rm', '-rf', src])
