Reorganize build process
[mspang/pyceo.git] / bin / csc-chsh
1 #!/usr/bin/python
2 """
3 chsh - change login shell
4
5 This utility imitates chsh(1) from the shadow password suite, but makes its
6 changes in the LDAP directory rather than in the passwd file.
7
8 When run from an unprivileged account, authentication will be performed
9 before the shell is changed, and the new shell must be listed in /etc/shells.
10 """
11 import os, sys, pwd, getopt, PAM
12 from csc.common.excep import InvalidArgument
13 from csc.adm import accounts
14
15 progname = os.path.basename(sys.argv[0])
16
17 def usage():
18     print "Usage: %s [-s shell] [username]" % progname
19     sys.exit(2)
20
21 def whoami():
22     uid = os.getuid()
23     username = os.getlogin()
24     if pwd.getpwnam(username).pw_uid != uid:
25         username = pwd.getpwuid(uid).pw_name
26     return (uid, username)
27
28 def authenticate(username):
29     auth = PAM.pam()
30     auth.start('chsh', username)
31     try:
32         auth.authenticate()
33         auth.acct_mgmt()
34     except PAM.error, resp:
35         print "%s: %s" % (progname, resp.args[0])
36         sys.exit(1)
37
38 def main():
39
40     pwuid, pwnam = whoami()
41
42     euid = os.geteuid()
43     os.setreuid(euid, euid)
44
45     try:
46         options, arguments = getopt.gnu_getopt(sys.argv[1:], 's:')
47         new_shell = None
48         for opt, val in options:
49             if opt == '-s':
50                 new_shell = val
51         if len(arguments) > 1:
52             usage()
53         elif len(arguments) == 1:
54             username = arguments[0]
55         else:
56             username = pwnam
57     except getopt.GetoptError, e:
58         usage()
59
60     try:
61         if pwuid and pwd.getpwnam(username).pw_uid != pwuid:
62             print "%s: You may not change the shell for %s." % (progname, username)
63             sys.exit(1)
64     except KeyError:
65         print "%s: unknown user %s" % (progname, username)
66         sys.exit(1)
67
68     try:
69         accounts.connect()
70         current_shell = accounts.get_shell(username)
71
72         if pwuid:
73             authenticate(username)
74
75         if not new_shell:
76             print "Changing the login shell for %s" % username
77             print "Enter the new value, or press ENTER for the default"
78             print "        Login Shell [%s]:" % current_shell,
79             new_shell = raw_input()
80             if not new_shell:
81                 new_shell = current_shell
82
83         if new_shell != current_shell:
84             accounts.update_shell(username, new_shell, pwuid != 0)
85
86     except InvalidArgument, e:
87         if e.argname == 'shell':
88             print "%s: %s: invalid shell" % (progname, new_shell)
89             sys.exit(1)
90         else:
91             raise
92
93 if __name__ == '__main__':
94     exceps = ( accounts.ConfigurationException, accounts.LDAPException,
95             accounts.KrbException, accounts.AccountException )
96     try:
97         main()
98     except KeyboardInterrupt:
99         sys.exit(130) 
100     except IOError, e:
101         print "%s: %s: %s" % (progname, e.filename, e.strerror)
102         sys.exit(1)
103     except exceps, e:
104         print "%s: %s" % (progname, e)
105         sys.exit(1)