;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2011 Free Software Foundation, Inc.
;; (copyright statements below in code to be updated with the above notice)
:group 'tramp
:type 'string)
-;; ksh on OpenBSD 4.5 requires, that $PS1 contains a `#' character for
+;; ksh on OpenBSD 4.5 requires that $PS1 contains a `#' character for
;; root users. It uses the `$' character for other users. In order
-;; to guarantee a proper prompt, we use "#$" for the prompt.
+;; to guarantee a proper prompt, we use "#$ " for the prompt.
(defvar tramp-end-of-output
(format
(tramp-login-args (("%h") ("-l" "%u")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "rcp")
- (tramp-copy-args (("%k" "-p") ("-r")))
+ (tramp-copy-args (("-p" "%k") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)))
;;;###tramp-autoload
(tramp-login-args (("%h") ("-l" "%u")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "rcp")
- (tramp-copy-args (("%k" "-p")))
+ (tramp-copy-args (("-p" "%k")))
(tramp-copy-keep-date t)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
- (tramp-copy-args (("-P" "%p") ("%k" "-p") ("-q") ("-r")))
+ (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
- (tramp-copy-args (("-1") ("-P" "%p") ("%k" "-p") ("-q") ("-r")))
+ (tramp-copy-args (("-1") ("-P" "%p") ("-p" "%k") ("-q") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
- (tramp-copy-args (("-2") ("-P" "%p") ("%k" "-p") ("-q") ("-r")))
+ (tramp-copy-args (("-2") ("-P" "%p") ("-p" "%k") ("-q") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
- (tramp-copy-args (("-P" "%p") ("%k" "-p") ("-q")
+ (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")
("-o" "ControlPath=%t.%%r@%%h:%%p")
("-o" "ControlMaster=auto")))
(tramp-copy-keep-date t)
+ (tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
("-o" "UserKnownHostsFile=/dev/null")
("-o" "StrictHostKeyChecking=no")))
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
- (tramp-copy-args (("%k" "-p")))
+ (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")))
(tramp-copy-keep-date t)
+ (tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
("-o" "UserKnownHostsFile=/dev/null")
("-o" "StrictHostKeyChecking=no")))
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "rsync")
- (tramp-copy-args (("-e" "ssh") ("%k" "-t") ("-r")))
+ (tramp-copy-args (("-e" "ssh") ("-t" "%k") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-keep-tmpfile t)
(tramp-copy-recursive t)))
(tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "rsync")
- (tramp-copy-args (("%k" "-t") ("-r")))
+ (tramp-copy-args (("-t" "%k") ("-r")))
(tramp-copy-env (("RSYNC_RSH")
(,(concat
"ssh"
(tramp-login-args (("-u" "%u") ("-s") ("-H") ("-p" "Password:")))
(tramp-remote-sh "/bin/sh")))
;;;###tramp-autoload
+(add-to-list 'tramp-methods
+ '("ksu"
+ (tramp-login-program "ksu")
+ (tramp-login-args (("%u") ("-q")))
+ (tramp-remote-sh "/bin/sh")))
+;;;###tramp-autoload
(add-to-list 'tramp-methods
'("krlogin"
(tramp-login-program "krlogin")
(tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "pscp")
- (tramp-copy-args (("-P" "%p") ("-scp") ("%k" "-p")
+ (tramp-copy-args (("-P" "%p") ("-scp") ("-p" "%k")
("-q") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "pscp")
- (tramp-copy-args (("-P" "%p") ("-sftp") ("%k" "-p")
+ (tramp-copy-args (("-P" "%p") ("-sftp") ("-p" "%k")
("-q") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-login-args (("%h") ("-l" "%u") ("sh" "-i")))
(tramp-remote-sh "/bin/sh -i")
(tramp-copy-program "fcp")
- (tramp-copy-args (("%k" "-p")))
+ (tramp-copy-args (("-p" "%k")))
(tramp-copy-keep-date t)))
+;;;###tramp-autoload
(add-to-list 'tramp-default-method-alist
`(,tramp-local-host-regexp "\\`root\\'" "su"))
+;;;###tramp-autoload
(add-to-list 'tramp-default-user-alist
- '("\\`su\\(do\\)?\\'" nil "root"))
+ `(,(concat "\\`" (regexp-opt '("su" "sudo" "ksu")) "\\'")
+ nil "root"))
+;; Do not add "ssh" based methods, otherwise ~/.ssh/config would be ignored.
+;;;###tramp-autoload
(add-to-list 'tramp-default-user-alist
- `("\\`r\\(em\\)?\\(cp\\|sh\\)\\|telnet\\|plink1?\\'"
+ `(,(concat
+ "\\`"
+ (regexp-opt
+ '("rcp" "remcp" "rsh" "telnet" "krlogin"
+ "plink" "plink1" "pscp" "psftp" "fcp"))
+ "\\'")
nil ,(user-login-name)))
(defconst tramp-completion-function-alist-rsh
(tramp-set-completion-function "telnet" tramp-completion-function-alist-telnet)
(tramp-set-completion-function "su" tramp-completion-function-alist-su)
(tramp-set-completion-function "sudo" tramp-completion-function-alist-su)
+(tramp-set-completion-function "ksu" tramp-completion-function-alist-su)
(tramp-set-completion-function "krlogin" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "plink" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "plink1" tramp-completion-function-alist-ssh)
`Default Directories' represent the list of directories given by
the command \"getconf PATH\". It is recommended to use this
entry on top of this list, because these are the default
-directories for POSIX compatible commands.
+directories for POSIX compatible commands. On remote hosts which
+do not offer the getconf command (like cygwin), the value
+\"/bin:/usr/bin\" is used instead of.
`Private Directories' are the settings of the $PATH environment,
as given in your `~/.profile'."
which might have been set in the init files like ~/.profile.
Special handling is applied to the PATH environment, which should
-not be set here. Instead of, it should be set via `tramp-remote-path'."
+not be set here. Instead, it should be set via `tramp-remote-path'."
:group 'tramp
:type '(repeat string))
(defconst tramp-perl-encode
"%s -e '
# This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-# Free Software Foundation, Inc.
+# Copyright (C) 2002-2011 Free Software Foundation, Inc.
use strict;
my %%trans = do {
(defconst tramp-perl-decode
"%s -e '
# This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-# Free Software Foundation, Inc.
+# Copyright (C) 2002-2011 Free Software Foundation, Inc.
use strict;
my %%trans = do {
(with-parsed-tramp-file-name (if t1 filename newname) nil
(if (and t1 t2)
- ;; Both are Tramp files. We shall optimize it, when the
+ ;; Both are Tramp files. We shall optimize it when the
;; methods for filename and newname are the same.
(let* ((dir-flag (file-directory-p filename))
(tmpfile (tramp-compat-make-temp-file localname dir-flag)))
'identity)
(if t2 (tramp-make-copy-program-file-name v) newname)))
- ;; Check for port number. Until now, there's no need for handling
- ;; like method, user, host.
- (setq host (tramp-file-name-real-host v)
- port (tramp-file-name-port v)
- port (or (and port (number-to-string port)) ""))
+ ;; Check for host and port number. We cannot use
+ ;; `tramp-file-name-port', because this returns also
+ ;; `tramp-default-port', which might clash with settings in
+ ;; "~/.ssh/config".
+ (setq host (tramp-file-name-host v)
+ port "")
+ (when (string-match tramp-host-with-port-regexp host)
+ (setq host (string-to-number (match-string 1 host))
+ port (string-to-number (match-string 2 host))))
;; Compose copy command.
(setq spec (format-spec-make
copy-args
(delete
;; " " has either been a replacement of "%k" (when
- ;; keep-date argument is non-nil), or a replacemtent
+ ;; keep-date argument is non-nil), or a replacement
;; for the whole keep-date sublist.
" "
(dolist
(append
copy-args
(let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
- (if (zerop (length (car y))) '(" ") y))))))
+ (if (member "" y) '(" ") y))))))
copy-env
(delq
nil
(tramp-send-command
v
(format "rm -rf %s" (tramp-shell-quote-argument localname))
- ;; Don't read the output, do it explicitely.
+ ;; Don't read the output, do it explicitly.
nil t)
;; Wait for the remote system to return to us...
;; This might take a while, allow it plenty of time.
(defun tramp-sh-handle-start-file-process (name buffer program &rest args)
"Like `start-file-process' for Tramp files."
(with-parsed-tramp-file-name default-directory nil
- (unwind-protect
- ;; When PROGRAM is nil, we just provide a tty.
- (let ((command
- (when (stringp program)
- (format "cd %s; exec %s"
- (tramp-shell-quote-argument localname)
- (mapconcat 'tramp-shell-quote-argument
- (cons program args) " "))))
- (tramp-process-connection-type
- (or (null program) tramp-process-connection-type))
- (name1 name)
- (i 0))
- (unless buffer
- ;; BUFFER can be nil. We use a temporary buffer.
- (setq buffer (generate-new-buffer tramp-temp-buffer-name)))
- (while (get-process name1)
- ;; NAME must be unique as process name.
- (setq i (1+ i)
- name1 (format "%s<%d>" name i)))
- (setq name name1)
- ;; Set the new process properties.
- (tramp-set-connection-property v "process-name" name)
- (tramp-set-connection-property v "process-buffer" buffer)
- ;; Activate narrowing in order to save BUFFER contents.
- ;; Clear also the modification time; otherwise we might be
- ;; interrupted by `verify-visited-file-modtime'.
- (with-current-buffer (tramp-get-connection-buffer v)
- (clear-visited-file-modtime)
- (narrow-to-region (point-max) (point-max)))
- (if command
- ;; Send the command.
- (tramp-send-command v command nil t) ; nooutput
- ;; Check, whether a pty is associated.
- (tramp-maybe-open-connection v)
- (unless (tramp-compat-process-get
- (tramp-get-connection-process v) 'remote-tty)
- (tramp-error
- v 'file-error "pty association is not supported for `%s'" name)))
- (let ((p (tramp-get-connection-process v)))
- ;; Set sentinel and query flag for this process.
- (tramp-set-connection-property p "vector" v)
- (set-process-sentinel p 'tramp-process-sentinel)
- (tramp-compat-set-process-query-on-exit-flag p t)
- ;; Return process.
- p))
- ;; Save exit.
- (with-current-buffer (tramp-get-connection-buffer v)
- (if (string-match tramp-temp-buffer-name (buffer-name))
- (progn
- (set-process-buffer (tramp-get-connection-process v) nil)
- (kill-buffer (current-buffer)))
- (widen)
- (goto-char (point-max))))
- (tramp-set-connection-property v "process-name" nil)
- (tramp-set-connection-property v "process-buffer" nil))))
+ ;; When PROGRAM is nil, we just provide a tty.
+ (let ((command
+ (when (stringp program)
+ (format "cd %s; exec %s"
+ (tramp-shell-quote-argument localname)
+ (mapconcat 'tramp-shell-quote-argument
+ (cons program args) " "))))
+ (tramp-process-connection-type
+ (or (null program) tramp-process-connection-type))
+ (bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
+ (name1 name)
+ (i 0))
+ (unwind-protect
+ (save-excursion
+ (save-restriction
+ (unless buffer
+ ;; BUFFER can be nil. We use a temporary buffer.
+ (setq buffer (generate-new-buffer tramp-temp-buffer-name)))
+ (while (get-process name1)
+ ;; NAME must be unique as process name.
+ (setq i (1+ i)
+ name1 (format "%s<%d>" name i)))
+ (setq name name1)
+ ;; Set the new process properties.
+ (tramp-set-connection-property v "process-name" name)
+ (tramp-set-connection-property v "process-buffer" buffer)
+ ;; Activate narrowing in order to save BUFFER contents.
+ ;; Clear also the modification time; otherwise we might
+ ;; be interrupted by `verify-visited-file-modtime'.
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (let ((buffer-undo-list t))
+ (clear-visited-file-modtime)
+ (narrow-to-region (point-max) (point-max))
+ (if command
+ ;; Send the command.
+ (tramp-send-command v command nil t) ; nooutput
+ ;; Check, whether a pty is associated.
+ (tramp-maybe-open-connection v)
+ (unless (tramp-compat-process-get
+ (tramp-get-connection-process v) 'remote-tty)
+ (tramp-error
+ v 'file-error
+ "pty association is not supported for `%s'" name)))))
+ (let ((p (tramp-get-connection-process v)))
+ ;; Set sentinel and query flag for this process.
+ (tramp-set-connection-property p "vector" v)
+ (set-process-sentinel p 'tramp-process-sentinel)
+ (tramp-compat-set-process-query-on-exit-flag p t)
+ ;; Return process.
+ p)))
+ ;; Save exit.
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (if (string-match tramp-temp-buffer-name (buffer-name))
+ (progn
+ (set-process-buffer (tramp-get-connection-process v) nil)
+ (kill-buffer (current-buffer)))
+ (set-buffer-modified-p bmp)))
+ (tramp-set-connection-property v "process-name" nil)
+ (tramp-set-connection-property v "process-buffer" nil)))))
(defun tramp-sh-handle-process-file
(program &optional infile destination display &rest args)
;; filename does not exist (eq modes nil) it has been
;; renamed to the backup file. This case `save-buffer'
;; handles permissions.
- ;; Ensure, that it is still readable.
+ ;; Ensure that it is still readable.
(when modes
(set-file-modes
tmpfile
(when (or (eq visit t) (stringp visit))
(let ((file-attr (file-attributes filename)))
(set-visited-file-modtime
- ;; We must pass modtime explicitely, because filename can
+ ;; We must pass modtime explicitly, because filename can
;; be different from (buffer-file-name), f.e. if
;; `file-precious-flag' is set.
(nth 5 file-attr))
(with-parsed-tramp-file-name filename nil
(cond
;; That's what we want: file names, for which checks are
- ;; applied. We assume, that VC uses only `file-exists-p' and
+ ;; applied. We assume that VC uses only `file-exists-p' and
;; `file-readable-p' checks; otherwise we must extend the
;; list. We do not perform any action, but return nil, in
;; order to keep `vc-registered' running.
vec 5
"Checking local compress command `%s', `%s' for sanity"
compress decompress)
- (unless (zerop (tramp-call-local-coding-command
- (format "echo %s | %s | %s"
- magic compress decompress) nil nil))
+ (unless
+ (zerop
+ (tramp-call-local-coding-command
+ (format
+ ;; Windows shells need the program file name after
+ ;; the pipe symbol be quoted if they use forward
+ ;; slashes as directory separators.
+ (if (memq system-type '(windows-nt))
+ "echo %s | \"%s\" | \"%s\""
+ "echo %s | %s | %s")
+ magic compress decompress) nil nil))
(throw 'next nil))
(tramp-message
vec 5
;; it is just a prefix for the ControlPath option
;; of ssh; the real temporary file has another
;; name, and it is created and protected by ssh.
- ;; It is also removed by ssh, when the connection
+ ;; It is also removed by ssh when the connection
;; is closed.
(tmpfile
(tramp-set-connection-property
(elt2 (memq 'tramp-own-remote-path remote-path))
(default-remote-path
(when elt1
- (condition-case nil
- (tramp-send-command-and-read
- vec "echo \\\"`getconf PATH`\\\"")
- ;; Default if "getconf" is not available.
- (error
+ (or
+ (tramp-send-command-and-read
+ vec
+ "x=`getconf PATH 2>/dev/null` && echo \\\"$x\\\" || echo nil")
+ ;; Default if "getconf" is not available.
+ (progn
(tramp-message
vec 3
"`getconf PATH' not successful, using default value \"%s\"."
(when elt2
(condition-case nil
(tramp-send-command-and-read vec "echo \\\"$PATH\\\"")
- ;; Default if "getconf" is not available.
(error
(tramp-message
vec 3 "$PATH not set, ignoring `tramp-own-remote-path'.")
((symbolp coding)
coding)
((and compress (string-match "decoding" prop))
- (format "(%s | %s >%%s)" coding compress))
+ (format
+ ;; Windows shells need the program file name after
+ ;; the pipe symbol be quoted if they use forward
+ ;; slashes as directory separators.
+ (if (and (string-match "local" prop)
+ (memq system-type '(windows-nt)))
+ "(%s | \"%s\" >%%s)"
+ "(%s | %s >%%s)")
+ coding compress))
(compress
- (format "(%s <%%s | %s)" compress coding))
+ (format
+ ;; Windows shells need the program file name after
+ ;; the pipe symbol be quoted if they use forward
+ ;; slashes as directory separators.
+ (if (and (string-match "local" prop)
+ (memq system-type '(windows-nt)))
+ "(%s <%%s | \"%s\")"
+ "(%s <%%s | %s)")
+ compress coding))
((string-match "decoding" prop)
(format "%s >%%s" coding))
(t
;; * It makes me wonder if tramp couldn't fall back to ssh when scp
;; isn't on the remote host. (Mark A. Hershberger)
;; * Use lsh instead of ssh. (Alfred M. Szmidt)
-;; * Optimize out-of-band copying, when both methods are scp-like (not
+;; * Optimize out-of-band copying when both methods are scp-like (not
;; rsync).
;; * Keep a second connection open for out-of-band methods like scp or
;; rsync.