class AutomateIt::AccountManager::PasswdPTY

AccountManager::PasswdPTY

An AccountManager driver for passwd command found on Unix-like systems using the Ruby PTY implementation.

WARNING: The Ruby PTY module is unreliable or unavailable on most platforms. It may hang indefinitely or report incorrect results. Every attempt has been made to work around these problems, but this is a low-level problem. You are strongly encouraged to install the expect program, which works flawlessly. Once the expect program is installed, passwords will be changed using the AccountManager::PasswdExpect driver, which works properly.

Public Instance Methods

passwd(user, password, opts={}) click to toggle source

See AccountManager#passwd

# File lib/automateit/account_manager/passwd_pty.rb, line 25
def passwd(user, password, opts={})
  log.info(PERROR+"Setting password with flaky Ruby PTY, which hangs or fails randomly. Install 'expect' (http://expect.nist.gov/) for reliable operation.")
  _passwd_helper(user, password, opts) do
    log.silence(Logger::WARN) do
      interpreter.mktemp do |filename|
        tries = 5
        exitstatus = nil
        begin
          exitstruct = _passwd_raw(user, password, opts)
          if exitstatus and not exitstruct.exitstatus.zero?
            # FIXME AccountManager::Linux#passwd -- The `passwd` command randomly returns exit status 10 even when it succeeds. What does this mean and how to deal with it?! Temporary workaround is to throw an error and force a retry.
            raise Errno::EPIPE.new("bad exitstatus %s" % exitstruct.exitstatus)
          end
        rescue Errno::EPIPE => e
          # FIXME AccountManager::Linux#passwd -- EPIPE exception randomly thrown even when `passwd` succeeds. How to eliminate it? How to differentiate between this false error and a real one?
          if tries <= 0
            raise e
          else
            tries -= 1
            retry
          end
        end
        return exitstruct.exitstatus.zero?
      end
    end
  end

end

Protected Instance Methods

_passwd_raw(user, password, opts={}) click to toggle source
# File lib/automateit/account_manager/passwd_pty.rb, line 54
def _passwd_raw(user, password, opts={})
  quiet = (opts[:quiet] or not log.info?)

  require 'open4'
  return Open4::popen4("passwd %s 2>&1" % user) do |pid, sin, sout, serr|
    $expect_verbose = ! quiet
    2.times do
      sout.expect(/:/)
      sleep 0.1 # Reduce chance of passwd thinking we're a robot :(
      sin.puts password
      puts "*" * 12 unless quiet
    end
  end
end