--- /dev/null
+#!/usr/bin/python2.4 --
+"""
+addhomedir - a script to create home directories for new users
+
+For the most part, this script mimics the behavior of adduser(8) when
+creating a home directory. It creates the directory, copies files
+from /etc/skel, sets permissions, and sets quotas.
+"""
+import os, sys, re, pwd, getopt, stat
+
+CONFIG_FILE = '/etc/csc/accounts.cf'
+
+safe_environment = ['LOGNAME', 'USERNAME', 'USER', 'HOME', 'TERM', 'LANG'
+ 'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGE', 'LC_MONETARY',
+ 'LC_NUMERIC', 'LC_TIME', 'UID', 'GID', 'SSH_CONNECTION', 'SSH_AUTH_SOCK',
+ 'SSH_CLIENT']
+
+for key in os.environ.keys():
+ if not key in safe_environment:
+ del os.environ[key]
+
+os.environ['PATH'] = '/usr/sbin:/sbin:/usr/bin:/bin'
+os.umask(0)
+
+for pathent in sys.path[:]:
+ if not pathent.find('/usr') == 0:
+ sys.path.remove(pathent)
+
+from csc.common import conf
+
+usage = "usage: %s [--quiet] username" % sys.argv[0]
+
+try:
+ options, arguments = getopt.gnu_getopt(sys.argv[1:], '', ['quiet'])
+except getopt.GetoptError, e:
+ print usage
+ sys.exit(2)
+
+if len(arguments) != 1:
+ print usage
+ sys.exit(2)
+
+quiet = ('--quiet','') in options
+program = os.path.basename(sys.argv[0])
+username = arguments[0]
+
+def fail(message):
+ print >> sys.stderr, "%s: %s" % (program, message)
+ sys.exit(1)
+
+def debug(message):
+ if not quiet:
+ print message
+
+def warn(message):
+ print >> sys.stderr, "warning: %s" % message
+
+try:
+ cfg = conf.read(CONFIG_FILE)
+except conf.ConfigurationException:
+ fail("could not import configuration from %s" % CONFIG_FILE)
+
+try:
+ string_fields = ['homedir_regex', 'skeleton_dir', 'quota_prototype']
+ integer_fields = ['homedir_min_uid', 'homedir_mode']
+ conf.check_string_fields(CONFIG_FILE, string_fields, cfg)
+ conf.check_integer_fields(CONFIG_FILE, integer_fields, cfg)
+except conf.ConfigurationException, e:
+ fail(e)
+
+if not os.path.isdir(cfg['skeleton_dir']):
+ fail("invalid skeleton dir %s" % cfg['skeleton_dir'])
+
+try:
+ pwent = pwd.getpwnam(username)
+ uid = pwent.pw_uid
+ gid = pwent.pw_gid
+ homedir = pwent.pw_dir
+except KeyError:
+ fail("%s: invalid user" % username)
+
+if uid < cfg['homedir_min_uid']:
+ fail("uid of account %s is less than homedir_min_uid" % username)
+
+if not re.match(cfg['homedir_regex'], homedir):
+ fail("homedir of account %s does not match homedir_regex" % username)
+
+if os.path.exists(homedir):
+ fail("home directory %s exists" % homedir)
+
+parentdir = os.path.dirname(homedir)
+if not os.path.isdir(parentdir):
+ fail("parent directory %s does not exist" % parentdir)
+
+try:
+ debug("creating %s" % homedir)
+ os.mkdir(homedir, cfg['homedir_mode'])
+ os.chown(homedir, uid, gid)
+
+ # copy files from /etc/skel or similar (location is configurable)
+ skel_files = os.listdir(cfg['skeleton_dir'])
+ for filename in skel_files:
+
+ srcpath = cfg['skeleton_dir'] + '/' + filename
+ destpath = homedir + '/' + filename
+ srcstat = os.lstat(srcpath)
+ perm = srcstat.st_mode & 0777
+
+ if srcstat.st_uid or srcstat.st_gid:
+ warn("skipping %s due to ownership" % srcpath)
+ continue
+
+ if stat.S_ISLNK(srcstat.st_mode):
+ linkdest = os.readlink(srcpath)
+ debug("linking %s to %s" % (destpath, linkdest))
+ os.symlink(linkdest, destpath)
+ os.lchown(destpath, uid, gid)
+
+ elif stat.S_ISDIR(srcstat.st_mode):
+ debug("adding directory %s" % destpath)
+ os.mkdir(destpath, perm)
+ os.chown(destpath, uid, gid)
+
+ elif stat.S_ISREG(srcstat.st_mode):
+ debug("adding %s" % destpath)
+ src = open(srcpath)
+ destfd = os.open(destpath, os.O_CREAT|os.O_EXCL|os.O_WRONLY, perm)
+ dest = os.fdopen(destfd, 'w')
+ dest.write(src.read())
+ src.close()
+ dest.close()
+ os.chown(destpath, uid, gid)
+
+ else:
+ warn("file type of %s not supported" % srcpath)
+
+ # set the user's quota
+ setquota = '/usr/sbin/setquota'
+ if os.access(setquota, os.X_OK):
+ protouser = cfg['quota_prototype']
+ debug("copying quotas from %s to %s" % (protouser, username))
+ args = [ setquota, '-u', '-p', protouser, username, '-a' ]
+ result = os.spawnv(os.P_WAIT, setquota, args)
+ if result:
+ warn("setquota returned error code %d" % result)
+ else:
+ warn("cannot find setquota, not setting quota")
+
+ debug("done!")
+
+except OSError, e:
+ fail(e)