#!/usr/bin/env python
'''Change passwords on the named machines.
    passmass host1 host2 host3 . . .
Note that login shell prompt on remote machine must end in # or $.
'''

import pexpect
import sys, getpass

USAGE = '''passmass host1 host2 host3 . . .'''
SHELL_PROMPT = '[#\$] '

def login(host, user, password):
    child = pexpect.spawn('ssh %s@%s'%(user, host))
    child.expect('password:')
    child.sendline(password)
    i = child.expect(['Permission denied', SHELL_PROMPT, 'Terminal type'])
    if i == 0:
        print 'Permission denied on host:', host
        return None
    elif i == 2:
        child.sendline('vt100')
        i = child.expect('[#\$] ')
    return child

def change_password(child, user, oldpassword, newpassword):
    child.sendline('passwd %s'%user)
    i = child.expect(['Old [Pp]assword', 'New [Pp]assword'])
    # Root does not require old password, so it gets to bypass the next step.
    if i == 0:
        child.sendline(oldpassword)
        child.expect('New [Pp]assword')
    child.sendline(newpassword)
    i = child.expect(['New [Pp]assword', 'Retype', 'Re-enter'])
    if i == 0:
        print 'Host did not like new password. Here is what it said...'
        print child.before
	child.send (chr(3)) # Ctrl-C
        child.sendline('') # This should tell remote passwd command to quit.
        return
    child.sendline(newpassword)

def main():
    if len(sys.argv) <= 1:
        print USAGE
        return 1

    user = raw_input('Username: ')
    password = getpass.getpass('Current Password: ')
    newpassword = getpass.getpass('New Password: ')
    newpasswordconfirm = getpass.getpass('Confirm New Password: ')
    if newpassword != newpasswordconfirm:
        print 'New Passwords do not match.'
        return 1

    for host in sys.argv[1:]:
        child = login(host, user, password)
        if child == None:
            print 'Could not login to host:', host
            continue
        print 'Changing password on host:', host
        change_password(child, user, password, newpassword)
        child.expect(SHELL_PROMPT)
        child.sendline('exit')

if __name__ == '__main__':
    try:
        main()
    except pexpect.ExceptionPexpect, e:
        print str(e)


