~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/ssh.py

  • Committer: Vincent Ladeuil
  • Date: 2010-10-07 06:08:01 UTC
  • mto: This revision was merged to the branch mainline in revision 5491.
  • Revision ID: v.ladeuil+lp@free.fr-20101007060801-wfdhizfhfmctl8qa
Fix some typos and propose a release planning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Robey Pointer <robey@lag.net>
 
1
# Copyright (C) 2006-2010 Robey Pointer <robey@lag.net>
2
2
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
126
126
        elif 'SSH Secure Shell' in version:
127
127
            trace.mutter('ssh implementation is SSH Corp.')
128
128
            vendor = SSHCorpSubprocessVendor()
129
 
        elif 'lsh' in version:
130
 
            trace.mutter('ssh implementation is GNU lsh.')
131
 
            vendor = LSHSubprocessVendor()
132
129
        # As plink user prompts are not handled currently, don't auto-detect
133
130
        # it by inspection below, but keep this vendor detection for if a path
134
131
        # is given in BZR_SSH. See https://bugs.launchpad.net/bugs/414743
135
132
        elif 'plink' in version and progname == 'plink':
136
133
            # Checking if "plink" was the executed argument as Windows
137
 
            # sometimes reports 'ssh -V' incorrectly with 'plink' in its
 
134
            # sometimes reports 'ssh -V' incorrectly with 'plink' in it's
138
135
            # version.  See https://bugs.launchpad.net/bzr/+bug/107155
139
136
            trace.mutter("ssh implementation is Putty's plink.")
140
137
            vendor = PLinkSubprocessVendor()
359
356
        # whatever) chunks.
360
357
        try:
361
358
            my_sock, subproc_sock = socket.socketpair()
362
 
            osutils.set_fd_cloexec(my_sock)
363
359
        except (AttributeError, socket.error):
364
360
            # This platform doesn't support socketpair(), so just use ordinary
365
361
            # pipes instead.
366
362
            stdin = stdout = subprocess.PIPE
367
 
            my_sock, subproc_sock = None, None
 
363
            sock = None
368
364
        else:
369
365
            stdin = stdout = subproc_sock
 
366
            sock = my_sock
370
367
        proc = subprocess.Popen(argv, stdin=stdin, stdout=stdout,
371
368
                                **os_specific_subprocess_params())
372
 
        if subproc_sock is not None:
373
 
            subproc_sock.close()
374
 
        return SSHSubprocessConnection(proc, sock=my_sock)
 
369
        return SSHSubprocessConnection(proc, sock=sock)
375
370
 
376
371
    def connect_sftp(self, username, password, host, port):
377
372
        try:
408
403
                                  command=None):
409
404
        args = [self.executable_path,
410
405
                '-oForwardX11=no', '-oForwardAgent=no',
411
 
                '-oClearAllForwardings=yes',
 
406
                '-oClearAllForwardings=yes', '-oProtocol=2',
412
407
                '-oNoHostAuthenticationForLocalhost=yes']
413
408
        if port is not None:
414
409
            args.extend(['-p', str(port)])
444
439
register_ssh_vendor('sshcorp', SSHCorpSubprocessVendor())
445
440
 
446
441
 
447
 
class LSHSubprocessVendor(SubprocessVendor):
448
 
    """SSH vendor that uses the 'lsh' executable from GNU"""
449
 
 
450
 
    executable_path = 'lsh'
451
 
 
452
 
    def _get_vendor_specific_argv(self, username, host, port, subsystem=None,
453
 
                                  command=None):
454
 
        args = [self.executable_path]
455
 
        if port is not None:
456
 
            args.extend(['-p', str(port)])
457
 
        if username is not None:
458
 
            args.extend(['-l', username])
459
 
        if subsystem is not None:
460
 
            args.extend(['--subsystem', subsystem, host])
461
 
        else:
462
 
            args.extend([host] + command)
463
 
        return args
464
 
 
465
 
register_ssh_vendor('lsh', LSHSubprocessVendor())
466
 
 
467
 
 
468
442
class PLinkSubprocessVendor(SubprocessVendor):
469
443
    """SSH vendor that uses the 'plink' executable from Putty."""
470
444
 
573
547
        return True
574
548
    except paramiko.PasswordRequiredException:
575
549
        password = ui.ui_factory.get_password(
576
 
            prompt=u'SSH %(filename)s password',
577
 
            filename=filename.decode(osutils._fs_enc))
 
550
            prompt='SSH %(filename)s password', filename=filename)
578
551
        try:
579
552
            key = pkey_class.from_private_key_file(filename, password)
580
553
            paramiko_transport.auth_publickey(username, key)
656
629
import weakref
657
630
_subproc_weakrefs = set()
658
631
 
659
 
def _close_ssh_proc(proc, sock):
 
632
def _close_ssh_proc(proc):
660
633
    """Carefully close stdin/stdout and reap the SSH process.
661
634
 
662
635
    If the pipes are already closed and/or the process has already been
663
636
    wait()ed on, that's ok, and no error is raised.  The goal is to do our best
664
637
    to clean up (whether or not a clean up was already tried).
665
638
    """
666
 
    funcs = []
667
 
    for closeable in (proc.stdin, proc.stdout, sock):
668
 
        # We expect that either proc (a subprocess.Popen) will have stdin and
669
 
        # stdout streams to close, or that we will have been passed a socket to
670
 
        # close, with the option not in use being None.
671
 
        if closeable is not None:
672
 
            funcs.append(closeable.close)
673
 
    funcs.append(proc.wait)
674
 
    for func in funcs:
675
 
        try:
676
 
            func()
 
639
    dotted_names = ['stdin.close', 'stdout.close', 'wait']
 
640
    for dotted_name in dotted_names:
 
641
        attrs = dotted_name.split('.')
 
642
        try:
 
643
            obj = proc
 
644
            for attr in attrs:
 
645
                obj = getattr(obj, attr)
 
646
        except AttributeError:
 
647
            # It's ok for proc.stdin or proc.stdout to be None.
 
648
            continue
 
649
        try:
 
650
            obj()
677
651
        except OSError:
678
652
            # It's ok for the pipe to already be closed, or the process to
679
653
            # already be finished.
718
692
        # to avoid leaving processes lingering indefinitely.
719
693
        def terminate(ref):
720
694
            _subproc_weakrefs.remove(ref)
721
 
            _close_ssh_proc(proc, sock)
 
695
            _close_ssh_proc(proc)
722
696
        _subproc_weakrefs.add(weakref.ref(self, terminate))
723
697
 
724
698
    def send(self, data):
734
708
            return os.read(self.proc.stdout.fileno(), count)
735
709
 
736
710
    def close(self):
737
 
        _close_ssh_proc(self.proc, self._sock)
 
711
        _close_ssh_proc(self.proc)
738
712
 
739
713
    def get_sock_or_pipes(self):
740
714
        if self._sock is not None: