tramp-sh.el 236 KB
Newer Older
Michael Albinus's avatar
Michael Albinus committed
1
;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections  -*- lexical-binding:t -*-
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1998-2020 Free Software Foundation, Inc.
4 5 6 7 8

;; (copyright statements below in code to be updated with the above notice)

;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
;;         Michael Albinus <michael.albinus@gmx.de>
9
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
;; Keywords: comm, processes
;; Package: tramp

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
26
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
27

28 29 30 31
;;; Commentary:

;; The file name handler implementation for ssh-alike remote connections.

32 33
;;; Code:

34
(eval-when-compile (require 'cl-lib))
35 36
(require 'tramp)

Michael Albinus's avatar
Michael Albinus committed
37 38
(declare-function dired-remove-file "dired-aux")
(defvar dired-compress-file-suffixes)
39
(defvar process-file-return-signal-string)
40 41 42 43
(defvar vc-handled-backends)
(defvar vc-bzr-program)
(defvar vc-git-program)
(defvar vc-hg-program)
44

45 46 47 48
;;;###tramp-autoload
(defconst tramp-default-remote-shell "/bin/sh"
  "The default remote shell Tramp applies.")

49
;;;###tramp-autoload
50
(defcustom tramp-inline-compress-start-size 4096
51
  "The minimum size of compressing where inline transfer.
52 53 54
When inline transfer, compress transferred data of file whose
size is this value or above (up to `tramp-copy-size-limit' for
out-of-band methods).
55 56
If it is nil, no compression at all will be applied."
  :group 'tramp
Michael Albinus's avatar
Michael Albinus committed
57
  :type '(choice (const nil) integer))
58

59
;;;###tramp-autoload
60
(defcustom tramp-copy-size-limit 10240
Michael Albinus's avatar
Michael Albinus committed
61 62 63
  "The maximum file size where inline copying is preferred over an \
out-of-the-band copy.
If it is nil, out-of-the-band copy will be used without a check."
64
  :group 'tramp
Michael Albinus's avatar
Michael Albinus committed
65
  :type '(choice (const nil) integer))
66 67 68

;;;###tramp-autoload
(defcustom tramp-terminal-type "dumb"
69
  "Value of TERM environment variable for logging in to remote host.
70 71 72 73
Because Tramp wants to parse the output of the remote shell, it is easily
confused by ANSI color escape sequences and suchlike.  Often, shell init
files conditionalize this setup based on the TERM environment variable."
  :group 'tramp
Michael Albinus's avatar
Michael Albinus committed
74
  :type 'string)
75

76
;;;###tramp-autoload
Michael Albinus's avatar
Michael Albinus committed
77
(defcustom tramp-histfile-override "~/.tramp_history"
78
  "When invoking a shell, override the HISTFILE with this value.
79 80 81
When setting to a string, it redirects the shell history to that
file.  Be careful when setting to \"/dev/null\"; this might
result in undesired results when using \"bash\" as shell.
82

Michael Albinus's avatar
Michael Albinus committed
83 84 85 86
The value t unsets any setting of HISTFILE, and sets both
HISTFILESIZE and HISTSIZE to 0.  If you set this variable to nil,
however, the *override* is disabled, so the history will go to
the default storage location, e.g. \"$HOME/.sh_history\"."
87
  :group 'tramp
Michael Albinus's avatar
Michael Albinus committed
88
  :version "25.2"
89
  :type '(choice (const :tag "Do not override HISTFILE" nil)
90
                 (const :tag "Unset HISTFILE" t)
Michael Albinus's avatar
Michael Albinus committed
91
                 (string :tag "Redirect to a file")))
92

93
;;;###tramp-autoload
Michael Albinus's avatar
Michael Albinus committed
94
(defconst tramp-display-escape-sequence-regexp "\e[[:digit:];[]+m"
Michael Albinus's avatar
Michael Albinus committed
95 96
  "Terminal control escape sequences for display attributes.")

Michael Albinus's avatar
Michael Albinus committed
97
(defconst tramp-device-escape-sequence-regexp "\e[[:digit:][]+n"
Michael Albinus's avatar
Michael Albinus committed
98
  "Terminal control escape sequences for device status.")
99

100
;; ksh on OpenBSD 4.5 requires that $PS1 contains a `#' character for
101
;; root users.  It uses the `$' character for other users.  In order
102
;; to guarantee a proper prompt, we use "#$ " for the prompt.
103 104 105 106 107 108

(defvar tramp-end-of-output
  (format
   "///%s#$"
   (md5 (concat (prin1-to-string process-environment) (current-time-string))))
  "String used to recognize end of output.
109
The `$' character at the end is quoted; the string cannot be
110 111 112 113 114 115
detected as prompt when being sent on echoing hosts, therefore.")

;;;###tramp-autoload
(defconst tramp-initial-end-of-output "#$ "
  "Prompt when establishing a connection.")

116 117 118
(defconst tramp-end-of-heredoc (md5 tramp-end-of-output)
  "String used to recognize end of heredoc strings.")

119
;;;###tramp-autoload
120
(defcustom tramp-use-ssh-controlmaster-options t
Michael Albinus's avatar
Michael Albinus committed
121 122 123
  "Whether to use `tramp-ssh-controlmaster-options'.
Set it to nil, if you use Control* or Proxy* options in your ssh
configuration."
124 125
  :group 'tramp
  :version "24.4"
Michael Albinus's avatar
Michael Albinus committed
126
  :type 'boolean)
127 128 129 130 131

(defvar tramp-ssh-controlmaster-options nil
  "Which ssh Control* arguments to use.

If it is a string, it should have the form
132
\"-o ControlMaster=auto -o ControlPath=\\='tramp.%%r@%%h:%%p\\='
133 134 135 136 137 138 139 140 141
-o ControlPersist=no\".  Percent characters in the ControlPath
spec must be doubled, because the string is used as format string.

Otherwise, it will be auto-detected by Tramp, if
`tramp-use-ssh-controlmaster-options' is non-nil.  The value
depends on the installed local ssh version.

The string is used in `tramp-methods'.")

142 143
;; Initialize `tramp-methods' with the supported methods.
;;;###tramp-autoload
144 145
(tramp--with-startup
 (add-to-list 'tramp-methods
146
              `("rcp"
147 148
                (tramp-login-program        "rsh")
                (tramp-login-args           (("%h") ("-l" "%u")))
149
                (tramp-remote-shell         ,tramp-default-remote-shell)
150 151 152 153 154 155 156
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "rcp")
                (tramp-copy-args            (("-p" "%k") ("-r")))
                (tramp-copy-keep-date       t)
                (tramp-copy-recursive       t)))
 (add-to-list 'tramp-methods
157
              `("remcp"
158 159
                (tramp-login-program        "remsh")
                (tramp-login-args           (("%h") ("-l" "%u")))
160
                (tramp-remote-shell         ,tramp-default-remote-shell)
161 162 163 164 165 166
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "rcp")
                (tramp-copy-args            (("-p" "%k")))
                (tramp-copy-keep-date       t)))
 (add-to-list 'tramp-methods
167
              `("scp"
168 169 170 171
                (tramp-login-program        "ssh")
                (tramp-login-args           (("-l" "%u") ("-p" "%p") ("%c")
				             ("-e" "none") ("%h")))
                (tramp-async-args           (("-q")))
172
                (tramp-remote-shell         ,tramp-default-remote-shell)
173 174 175
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "scp")
176 177
                (tramp-copy-args            (("-P" "%p") ("-p" "%k") ("-q")
					     ("-r") ("%c")))
178 179 180
                (tramp-copy-keep-date       t)
                (tramp-copy-recursive       t)))
 (add-to-list 'tramp-methods
181
              `("scpx"
182 183
                (tramp-login-program        "ssh")
                (tramp-login-args           (("-l" "%u") ("-p" "%p") ("%c")
184 185
				             ("-e" "none") ("-t" "-t") ("%h")
					     ("%l")))
186
                (tramp-async-args           (("-q")))
187
                (tramp-remote-shell         ,tramp-default-remote-shell)
188 189 190 191 192 193 194 195
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "scp")
                (tramp-copy-args            (("-P" "%p") ("-p" "%k")
				             ("-q") ("-r") ("%c")))
                (tramp-copy-keep-date       t)
                (tramp-copy-recursive       t)))
 (add-to-list 'tramp-methods
196
              `("rsync"
197 198 199 200
                (tramp-login-program        "ssh")
                (tramp-login-args           (("-l" "%u") ("-p" "%p") ("%c")
				             ("-e" "none") ("%h")))
                (tramp-async-args           (("-q")))
201
                (tramp-remote-shell         ,tramp-default-remote-shell)
202 203 204
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "rsync")
205 206
                (tramp-copy-args            (("-t" "%k") ("-p") ("-r") ("-s")
					     ("-c")))
207 208 209 210 211
                (tramp-copy-env             (("RSYNC_RSH") ("ssh" "%c")))
                (tramp-copy-keep-date       t)
                (tramp-copy-keep-tmpfile    t)
                (tramp-copy-recursive       t)))
 (add-to-list 'tramp-methods
212
              `("rsh"
213 214
                (tramp-login-program        "rsh")
                (tramp-login-args           (("%h") ("-l" "%u")))
215
                (tramp-remote-shell         ,tramp-default-remote-shell)
216 217 218
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
219
              `("remsh"
220 221
                (tramp-login-program        "remsh")
                (tramp-login-args           (("%h") ("-l" "%u")))
222
                (tramp-remote-shell         ,tramp-default-remote-shell)
223 224 225
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
226
              `("ssh"
227 228 229 230
                (tramp-login-program        "ssh")
                (tramp-login-args           (("-l" "%u") ("-p" "%p") ("%c")
				             ("-e" "none") ("%h")))
                (tramp-async-args           (("-q")))
231
                (tramp-remote-shell         ,tramp-default-remote-shell)
232 233 234
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
235
              `("sshx"
236 237
                (tramp-login-program        "ssh")
                (tramp-login-args           (("-l" "%u") ("-p" "%p") ("%c")
238 239
				             ("-e" "none") ("-t" "-t") ("%h")
					     ("%l")))
240
                (tramp-async-args           (("-q")))
241
                (tramp-remote-shell         ,tramp-default-remote-shell)
242 243 244
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
245
              `("telnet"
246
                (tramp-login-program        "telnet")
247
                (tramp-login-args           (("%h") ("%p") ("%n")))
248
                (tramp-remote-shell         ,tramp-default-remote-shell)
249 250 251
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
252
              `("nc"
253
                (tramp-login-program        "telnet")
254
                (tramp-login-args           (("%h") ("%p") ("%n")))
255
                (tramp-remote-shell         ,tramp-default-remote-shell)
256 257 258 259 260 261 262 263 264
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "nc")
                ;; We use "-v" for better error tracking.
                (tramp-copy-args            (("-w" "1") ("-v") ("%h") ("%r")))
                (tramp-remote-copy-program  "nc")
                ;; We use "-p" as required for newer busyboxes.  For older
                ;; busybox/nc versions, the value must be (("-l") ("%r")).  This
                ;; can be achieved by tweaking `tramp-connection-properties'.
265
                (tramp-remote-copy-args     (("-l") ("-p" "%r") ("%n")))))
266
 (add-to-list 'tramp-methods
267
              `("su"
268 269
                (tramp-login-program        "su")
                (tramp-login-args           (("-") ("%u")))
270
                (tramp-remote-shell         ,tramp-default-remote-shell)
271 272 273 274
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-connection-timeout   10)))
 (add-to-list 'tramp-methods
275
              `("sg"
276 277
                (tramp-login-program        "sg")
                (tramp-login-args           (("-") ("%u")))
278
                (tramp-remote-shell         ,tramp-default-remote-shell)
279 280 281
                (tramp-remote-shell-args    ("-c"))
                (tramp-connection-timeout   10)))
 (add-to-list 'tramp-methods
282
              `("sudo"
283
                (tramp-login-program        "sudo")
284 285 286
                ;; The password template must be masked.  Otherwise,
                ;; it could be interpreted as password prompt if the
                ;; remote host echoes the command.
287
                (tramp-login-args           (("-u" "%u") ("-s") ("-H")
288 289
				             ("-p" "P\"\"a\"\"s\"\"s\"\"w\"\"o\"\"r\"\"d\"\":")
                                             ("%l")))
290
                (tramp-remote-shell         ,tramp-default-remote-shell)
291 292 293 294 295
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-connection-timeout   10)
                (tramp-session-timeout      300)))
 (add-to-list 'tramp-methods
296
              `("doas"
297 298
                (tramp-login-program        "doas")
                (tramp-login-args           (("-u" "%u") ("-s")))
299
                (tramp-remote-shell         ,tramp-default-remote-shell)
300 301 302 303
                (tramp-remote-shell-args    ("-c"))
                (tramp-connection-timeout   10)
                (tramp-session-timeout      300)))
 (add-to-list 'tramp-methods
304
              `("ksu"
305 306
                (tramp-login-program        "ksu")
                (tramp-login-args           (("%u") ("-q")))
307
                (tramp-remote-shell         ,tramp-default-remote-shell)
308 309 310 311
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-connection-timeout   10)))
 (add-to-list 'tramp-methods
312
              `("krlogin"
313 314
                (tramp-login-program        "krlogin")
                (tramp-login-args           (("%h") ("-l" "%u") ("-x")))
315
                (tramp-remote-shell         ,tramp-default-remote-shell)
316 317 318 319 320
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
              `("plink"
                (tramp-login-program        "plink")
321 322
                (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh")
					     ("-t") ("%h") ("\"")
323 324 325 326
				             (,(format
				                "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
				                tramp-terminal-type
				                tramp-initial-end-of-output))
327 328
				             ("%l") ("\"")))
                (tramp-remote-shell         ,tramp-default-remote-shell)
329 330 331 332 333 334 335 336 337 338
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
              `("plinkx"
                (tramp-login-program        "plink")
                (tramp-login-args           (("-load") ("%h") ("-t") ("\"")
				             (,(format
				                "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
				                tramp-terminal-type
				                tramp-initial-end-of-output))
339 340
				             ("%l") ("\"")))
                (tramp-remote-shell         ,tramp-default-remote-shell)
341 342 343 344 345
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))))
 (add-to-list 'tramp-methods
              `("pscp"
                (tramp-login-program        "plink")
346 347
                (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh")
					     ("-t") ("%h") ("\"")
348 349 350 351
				             (,(format
				                "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
				                tramp-terminal-type
				                tramp-initial-end-of-output))
352 353
				             ("%l") ("\"")))
                (tramp-remote-shell         ,tramp-default-remote-shell)
354 355 356
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "pscp")
357 358
                (tramp-copy-args            (("-l" "%u") ("-P" "%p") ("-scp")
					     ("-p" "%k") ("-q") ("-r")))
359 360 361 362 363
                (tramp-copy-keep-date       t)
                (tramp-copy-recursive       t)))
 (add-to-list 'tramp-methods
              `("psftp"
                (tramp-login-program        "plink")
364 365
                (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh")
					     ("-t") ("%h") ("\"")
366 367 368 369
				             (,(format
				                "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
				                tramp-terminal-type
				                tramp-initial-end-of-output))
370 371
				             ("%l") ("\"")))
                (tramp-remote-shell         ,tramp-default-remote-shell)
372 373 374
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-c"))
                (tramp-copy-program         "pscp")
375 376
                (tramp-copy-args            (("-l" "%u") ("-P" "%p") ("-sftp")
					     ("-p" "%k") ("-q")))
377 378
                (tramp-copy-keep-date       t)))
 (add-to-list 'tramp-methods
379
              `("fcp"
380 381
                (tramp-login-program        "fsh")
                (tramp-login-args           (("%h") ("-l" "%u") ("sh" "-i")))
382
                (tramp-remote-shell         ,tramp-default-remote-shell)
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
                (tramp-remote-shell-login   ("-l"))
                (tramp-remote-shell-args    ("-i") ("-c"))
                (tramp-copy-program         "fcp")
                (tramp-copy-args            (("-p" "%k")))
                (tramp-copy-keep-date       t)))

 (add-to-list 'tramp-default-method-alist
	      `(,tramp-local-host-regexp "\\`root\\'" "su"))

 (add-to-list 'tramp-default-user-alist
	      `(,(concat "\\`" (regexp-opt '("su" "sudo" "doas" "ksu")) "\\'")
	        nil "root"))
 ;; Do not add "ssh" based methods, otherwise ~/.ssh/config would be ignored.
 ;; Do not add "plink" based methods, they ask interactively for the user.
 (add-to-list 'tramp-default-user-alist
	      `(,(concat
		  "\\`"
		  (regexp-opt
		   '("rcp" "remcp" "rsh" "telnet" "nc" "krlogin" "fcp"))
		  "\\'")
	        nil ,(user-login-name))))
404

405
;;;###tramp-autoload
406 407 408 409 410
(defconst tramp-completion-function-alist-rsh
  '((tramp-parse-rhosts "/etc/hosts.equiv")
    (tramp-parse-rhosts "~/.rhosts"))
  "Default list of (FUNCTION FILE) pairs to be examined for rsh methods.")

411
;;;###tramp-autoload
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
(defconst tramp-completion-function-alist-ssh
  '((tramp-parse-rhosts      "/etc/hosts.equiv")
    (tramp-parse-rhosts      "/etc/shosts.equiv")
    (tramp-parse-shosts      "/etc/ssh_known_hosts")
    (tramp-parse-sconfig     "/etc/ssh_config")
    (tramp-parse-shostkeys   "/etc/ssh2/hostkeys")
    (tramp-parse-sknownhosts "/etc/ssh2/knownhosts")
    (tramp-parse-rhosts      "~/.rhosts")
    (tramp-parse-rhosts      "~/.shosts")
    (tramp-parse-shosts      "~/.ssh/known_hosts")
    (tramp-parse-sconfig     "~/.ssh/config")
    (tramp-parse-shostkeys   "~/.ssh2/hostkeys")
    (tramp-parse-sknownhosts "~/.ssh2/knownhosts"))
  "Default list of (FUNCTION FILE) pairs to be examined for ssh methods.")

427
;;;###tramp-autoload
428 429 430 431
(defconst tramp-completion-function-alist-telnet
  '((tramp-parse-hosts "/etc/hosts"))
  "Default list of (FUNCTION FILE) pairs to be examined for telnet methods.")

432
;;;###tramp-autoload
433 434 435 436
(defconst tramp-completion-function-alist-su
  '((tramp-parse-passwd "/etc/passwd"))
  "Default list of (FUNCTION FILE) pairs to be examined for su methods.")

Michael Albinus's avatar
Michael Albinus committed
437 438 439 440 441
;;;###tramp-autoload
(defconst tramp-completion-function-alist-sg
  '((tramp-parse-etc-group "/etc/group"))
  "Default list of (FUNCTION FILE) pairs to be examined for sg methods.")

442
;;;###tramp-autoload
443
(defconst tramp-completion-function-alist-putty
Michael Albinus's avatar
Michael Albinus committed
444 445 446 447
  `((tramp-parse-putty
     ,(if (memq system-type '(windows-nt))
	  "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions"
	"~/.putty/sessions")))
Michael Albinus's avatar
Michael Albinus committed
448
 "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.")
449

450
;;;###tramp-autoload
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
(tramp--with-startup
 (tramp-set-completion-function "rcp" tramp-completion-function-alist-rsh)
 (tramp-set-completion-function "remcp" tramp-completion-function-alist-rsh)
 (tramp-set-completion-function "scp" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function "scpx" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function "rsync" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function "rsh" tramp-completion-function-alist-rsh)
 (tramp-set-completion-function "remsh" tramp-completion-function-alist-rsh)
 (tramp-set-completion-function "ssh" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function "sshx" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function
  "telnet" tramp-completion-function-alist-telnet)
 (tramp-set-completion-function "nc" 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 "doas" tramp-completion-function-alist-su)
 (tramp-set-completion-function "ksu" tramp-completion-function-alist-su)
 (tramp-set-completion-function "sg" tramp-completion-function-alist-sg)
 (tramp-set-completion-function
  "krlogin" tramp-completion-function-alist-rsh)
 (tramp-set-completion-function "plink" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function
  "plinkx" tramp-completion-function-alist-putty)
 (tramp-set-completion-function "pscp" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function "psftp" tramp-completion-function-alist-ssh)
 (tramp-set-completion-function "fcp" tramp-completion-function-alist-ssh))
477 478 479 480

;; "getconf PATH" yields:
;; HP-UX: /usr/bin:/usr/ccs/bin:/opt/ansic/bin:/opt/langtools/bin:/opt/fortran/bin
;; Solaris: /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin
Michael Albinus's avatar
Michael Albinus committed
481
;; GNU/Linux (Debian, Suse, RHEL): /bin:/usr/bin
482
;; FreeBSD, DragonFly: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
483
;; Darwin: /usr/bin:/bin:/usr/sbin:/sbin
484
;; IRIX64: /usr/bin
485
;; QNAP QTS: ---
486
;; Hydra: /run/current-system/sw/bin:/bin:/usr/bin
Michael Albinus's avatar
Michael Albinus committed
487
;;;###tramp-autoload
488
(defcustom tramp-remote-path
489 490 491
  '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
    "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin"
    "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
Michael Albinus's avatar
Michael Albinus committed
492
    "/opt/bin" "/opt/sbin" "/opt/local/bin")
493
  "List of directories to search for executables on remote host.
494 495 496
For every remote host, this variable will be set buffer local,
keeping the list of existing directories on that host.

Michael Albinus's avatar
Michael Albinus committed
497 498
You can use \"~\" in this list, but when searching for a shell which groks
tilde expansion, all directory names starting with \"~\" will be ignored.
499 500 501

`Default Directories' represent the list of directories given by
the command \"getconf PATH\".  It is recommended to use this
502
entry on head of this list, because these are the default
503 504
directories for POSIX compatible commands.  On remote hosts which
do not offer the getconf command (like cygwin), the value
505
\"/bin:/usr/bin\" is used instead.  This entry is represented in
506
the list by the special value `tramp-default-remote-path'.
507 508

`Private Directories' are the settings of the $PATH environment,
509 510
as given in your `~/.profile'.  This entry is represented in
the list by the special value `tramp-own-remote-path'."
511 512 513 514
  :group 'tramp
  :type '(repeat (choice
		  (const :tag "Default Directories" tramp-default-remote-path)
		  (const :tag "Private Directories" tramp-own-remote-path)
Michael Albinus's avatar
Michael Albinus committed
515
		  (string :tag "Directory"))))
516

Michael Albinus's avatar
Michael Albinus committed
517
;;;###tramp-autoload
518
(defcustom tramp-remote-process-environment
Daniel Pittman's avatar
Daniel Pittman committed
519
  '("ENV=''" "TMOUT=0" "LC_CTYPE=''"
520
    "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH=" "PAGER=cat"
521
    "autocorrect=" "correct=")
522
  "List of environment variables to be set on the remote host.
523 524

Each element should be a string of the form ENVVARNAME=VALUE.  An
Paul Eggert's avatar
Paul Eggert committed
525
entry ENVVARNAME= disables the corresponding environment variable,
526 527
which might have been set in the init files like ~/.profile.

Daniel Pittman's avatar
Daniel Pittman committed
528 529 530 531 532 533 534 535
Special handling is applied to some environment variables,
which should not be set here:

The PATH environment variable should be set via `tramp-remote-path'.

The TERM environment variable should be set via `tramp-terminal-type'.

The INSIDE_EMACS environment variable will automatically be set
Michael Albinus's avatar
Michael Albinus committed
536
based on the Tramp and Emacs versions, and should not be set here."
537
  :group 'tramp
538
  :version "26.1"
Michael Albinus's avatar
Michael Albinus committed
539
  :type '(repeat string))
540

Michael Albinus's avatar
Michael Albinus committed
541
;;;###tramp-autoload
542
(defcustom tramp-sh-extra-args
543
  '(("/bash\\'" . "-noediting -norc -noprofile")
544
    ("/zsh\\'" . "-f +Z -V"))
545
  "Alist specifying extra arguments to pass to the remote shell.
546 547
Entries are (REGEXP . ARGS) where REGEXP is a regular expression
matching the shell file name and ARGS is a string specifying the
548 549
arguments.  These arguments shall disable line editing, see
`tramp-open-shell'.
550 551 552 553 554

This variable is only used when Tramp needs to start up another shell
for tilde expansion.  The extra arguments should typically prevent the
shell from reading its init file."
  :group 'tramp
555
  :version "27.1"
Michael Albinus's avatar
Michael Albinus committed
556
  :type '(alist :key-type regexp :value-type string))
557 558 559 560 561 562 563 564 565 566

(defconst tramp-actions-before-shell
  '((tramp-login-prompt-regexp tramp-action-login)
    (tramp-password-prompt-regexp tramp-action-password)
    (tramp-wrong-passwd-regexp tramp-action-permission-denied)
    (shell-prompt-pattern tramp-action-succeed)
    (tramp-shell-prompt-pattern tramp-action-succeed)
    (tramp-yesno-prompt-regexp tramp-action-yesno)
    (tramp-yn-prompt-regexp tramp-action-yn)
    (tramp-terminal-prompt-regexp tramp-action-terminal)
567
    (tramp-antispoof-regexp tramp-action-confirm-message)
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
    (tramp-process-alive-regexp tramp-action-process-alive))
  "List of pattern/action pairs.
Whenever a pattern matches, the corresponding action is performed.
Each item looks like (PATTERN ACTION).

The PATTERN should be a symbol, a variable.  The value of this
variable gives the regular expression to search for.  Note that the
regexp must match at the end of the buffer, \"\\'\" is implicitly
appended to it.

The ACTION should also be a symbol, but a function.  When the
corresponding PATTERN matches, the ACTION function is called.")

(defconst tramp-actions-copy-out-of-band
  '((tramp-password-prompt-regexp tramp-action-password)
    (tramp-wrong-passwd-regexp tramp-action-permission-denied)
    (tramp-copy-failed-regexp tramp-action-permission-denied)
    (tramp-process-alive-regexp tramp-action-out-of-band))
  "List of pattern/action pairs.
This list is used for copying/renaming with out-of-band methods.

See `tramp-actions-before-shell' for more info.")

(defconst tramp-uudecode
Michael Albinus's avatar
Michael Albinus committed
592 593 594
  "(echo begin 600 %t; tail -n +2) | uudecode
cat %t
rm -f %t"
595 596 597 598 599 600 601 602 603 604
  "Shell function to implement `uudecode' to standard output.
Many systems support `uudecode -o /dev/stdout' or `uudecode -o -'
for this or `uudecode -p', but some systems don't, and for them
we have this shell function.")

(defconst tramp-perl-file-truename
  "%s -e '
use File::Spec;
use Cwd \"realpath\";

605 606
sub myrealpath {
    my ($file) = @_;
607
    return realpath($file) if (-e $file || -l $file);
608 609
}

610 611
sub recursive {
    my ($volume, @dirs) = @_;
612
    my $real = myrealpath(File::Spec->catpath(
613 614 615 616 617 618 619 620 621 622 623 624 625
                   $volume, File::Spec->catdir(@dirs), \"\"));
    if ($real) {
        my ($vol, $dir) = File::Spec->splitpath($real, 1);
        return ($vol, File::Spec->splitdir($dir));
    }
    else {
        my $last = pop(@dirs);
        ($volume, @dirs) = recursive($volume, @dirs);
        push(@dirs, $last);
        return ($volume, @dirs);
    }
}

626
$result = myrealpath($ARGV[0]);
627 628 629 630 631 632 633
if (!$result) {
    my ($vol, $dir) = File::Spec->splitpath($ARGV[0], 1);
    ($vol, @dirs) = recursive($vol, File::Spec->splitdir($dir));

    $result = File::Spec->catpath($vol, File::Spec->catdir(@dirs), \"\");
}

634
$result =~ s/\"/\\\\\"/g;
635 636 637 638 639 640 641 642
print \"\\\"$result\\\"\\n\";
' \"$1\" 2>/dev/null"
  "Perl script to produce output suitable for use with `file-truename'
on the remote file system.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-perl-file-name-all-completions
Michael Albinus's avatar
Michael Albinus committed
643
  "%s -e '
644 645 646
opendir(d, $ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");
@files = readdir(d); closedir(d);
foreach $f (@files) {
Michael Albinus's avatar
Michael Albinus committed
647 648 649 650 651
 if (-d \"$ARGV[0]/$f\") {
  print \"$f/\\n\";
 }
 else {
  print \"$f\\n\";
652 653 654
 }
}
print \"ok\\n\"
Michael Albinus's avatar
Michael Albinus committed
655
' \"$1\" 2>/dev/null"
656 657 658 659 660 661 662 663 664 665
  "Perl script to produce output suitable for use with
`file-name-all-completions' on the remote file system.  Escape
sequence %s is replaced with name of Perl binary.  This string is
passed to `format', so percent characters need to be doubled.")

;; Perl script to implement `file-attributes' in a Lisp `read'able
;; output.  If you are hacking on this, note that you get *no* output
;; unless this spits out a complete line, including the '\n' at the
;; end.
;; The device number is returned as "-1", because there will be a virtual
666
;; device number set in `tramp-sh-handle-file-attributes'.
667 668 669 670 671 672 673 674 675 676
(defconst tramp-perl-file-attributes
  "%s -e '
@stat = lstat($ARGV[0]);
if (!@stat) {
    print \"nil\\n\";
    exit 0;
}
if (($stat[2] & 0170000) == 0120000)
{
    $type = readlink($ARGV[0]);
Michael Albinus's avatar
Michael Albinus committed
677
    $type =~ s/\"/\\\\\"/g;
678 679 680 681 682 683 684 685 686 687 688 689 690
    $type = \"\\\"$type\\\"\";
}
elsif (($stat[2] & 0170000) == 040000)
{
    $type = \"t\";
}
else
{
    $type = \"nil\"
};
$uid = ($ARGV[1] eq \"integer\") ? $stat[4] : \"\\\"\" . getpwuid($stat[4]) . \"\\\"\";
$gid = ($ARGV[1] eq \"integer\") ? $stat[5] : \"\\\"\" . getgrgid($stat[5]) . \"\\\"\";
printf(
691
    \"(%%s %%u %%s %%s (%%u %%u) (%%u %%u) (%%u %%u) %%u %%u t %%u -1)\\n\",
692 693 694 695 696 697 698 699 700 701 702 703
    $type,
    $stat[3],
    $uid,
    $gid,
    $stat[8] >> 16 & 0xffff,
    $stat[8] & 0xffff,
    $stat[9] >> 16 & 0xffff,
    $stat[9] & 0xffff,
    $stat[10] >> 16 & 0xffff,
    $stat[10] & 0xffff,
    $stat[7],
    $stat[2],
Michael Albinus's avatar
Michael Albinus committed
704
    $stat[1]
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
);' \"$1\" \"$2\" 2>/dev/null"
  "Perl script to produce output suitable for use with `file-attributes'
on the remote file system.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-perl-directory-files-and-attributes
  "%s -e '
chdir($ARGV[0]) or printf(\"\\\"Cannot change to $ARGV[0]: $''!''\\\"\\n\"), exit();
opendir(DIR,\".\") or printf(\"\\\"Cannot open directory $ARGV[0]: $''!''\\\"\\n\"), exit();
@list = readdir(DIR);
closedir(DIR);
$n = scalar(@list);
printf(\"(\\n\");
for($i = 0; $i < $n; $i++)
{
    $filename = $list[$i];
    @stat = lstat($filename);
    if (($stat[2] & 0170000) == 0120000)
    {
        $type = readlink($filename);
Michael Albinus's avatar
Michael Albinus committed
726
        $type =~ s/\"/\\\\\"/g;
727 728 729 730 731 732 733 734 735 736 737 738
        $type = \"\\\"$type\\\"\";
    }
    elsif (($stat[2] & 0170000) == 040000)
    {
        $type = \"t\";
    }
    else
    {
        $type = \"nil\"
    };
    $uid = ($ARGV[1] eq \"integer\") ? $stat[4] : \"\\\"\" . getpwuid($stat[4]) . \"\\\"\";
    $gid = ($ARGV[1] eq \"integer\") ? $stat[5] : \"\\\"\" . getgrgid($stat[5]) . \"\\\"\";
Michael Albinus's avatar
Michael Albinus committed
739
    $filename =~ s/\"/\\\\\"/g;
740
    printf(
741
        \"(\\\"%%s\\\" %%s %%u %%s %%s (%%u %%u) (%%u %%u) (%%u %%u) %%u %%u t %%u -1)\\n\",
742 743 744 745 746 747 748 749 750 751 752 753 754
        $filename,
        $type,
        $stat[3],
        $uid,
        $gid,
        $stat[8] >> 16 & 0xffff,
        $stat[8] & 0xffff,
        $stat[9] >> 16 & 0xffff,
        $stat[9] & 0xffff,
        $stat[10] >> 16 & 0xffff,
        $stat[10] & 0xffff,
        $stat[7],
        $stat[2],
755
        $stat[1]);
756 757
}
printf(\")\\n\");' \"$1\" \"$2\" 2>/dev/null"
758
  "Perl script implementing `directory-files-and-attributes' as Lisp `read'able
759 760 761 762 763 764
output.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.")

;; These two use base64 encoding.
(defconst tramp-perl-encode-with-module
765
  "%s -MMIME::Base64 -0777 -ne 'print encode_base64($_)' %n"
766 767 768 769 770 771 772
  "Perl program to use for encoding a file.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.
This implementation requires the MIME::Base64 Perl module to be installed
on the remote host.")

(defconst tramp-perl-decode-with-module
773
  "%s -MMIME::Base64 -0777 -ne 'print decode_base64($_)' %n"
774 775 776 777 778 779 780 781 782
  "Perl program to use for decoding a file.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.
This implementation requires the MIME::Base64 Perl module to be installed
on the remote host.")

(defconst tramp-perl-encode
  "%s -e '
# This script contributed by Juanma Barranquero <lektu@terra.es>.
Paul Eggert's avatar
Paul Eggert committed
783
# Copyright (C) 2002-2020 Free Software Foundation, Inc.
784 785 786 787 788 789 790
use strict;

my %%trans = do {
    my $i = 0;
    map {(substr(unpack(q(B8), chr $i++), 2, 6), $_)}
      split //, q(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/);
};
791
my $data;
792 793 794

# We read in chunks of 54 bytes, to generate output lines
# of 72 chars (plus end of line)
795
while (read STDIN, $data, 54) {
796 797
    my $pad = q();

798 799
    # Only for the last chunk, and only if did not fill the last
    # three-byte packet
800 801 802 803 804 805 806 807 808 809 810 811 812 813
    if (eof) {
        my $mod = length($data) %% 3;
        $pad = q(=) x (3 - $mod) if $mod;
    }

    # Not the fastest method, but it is simple: unpack to binary string, split
    # by groups of 6 bits and convert back from binary to byte; then map into
    # the translation table
    print
      join q(),
        map($trans{$_},
            (substr(unpack(q(B*), $data) . q(00000), 0, 432) =~ /....../g)),
              $pad,
                qq(\\n);
814
}' %n"
815 816 817 818 819 820 821
  "Perl program to use for encoding a file.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-perl-decode
  "%s -e '
# This script contributed by Juanma Barranquero <lektu@terra.es>.
Paul Eggert's avatar
Paul Eggert committed
822
# Copyright (C) 2002-2020 Free Software Foundation, Inc.
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
use strict;

my %%trans = do {
    my $i = 0;
    map {($_, substr(unpack(q(B8), chr $i++), 2, 6))}
      split //, q(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)
};

my %%bytes = map {(unpack(q(B8), chr $_), chr $_)} 0 .. 255;

binmode(\\*STDOUT);

# We are going to accumulate into $pending to accept any line length
# (we do not check they are <= 76 chars as the RFC says)
my $pending = q();

while (my $data = <STDIN>) {
    chomp $data;

    # If we find one or two =, we have reached the end and
    # any following data is to be discarded
    my $finished = $data =~ s/(==?).*/$1/;
    $pending .= $data;

    my $len = length($pending);
    my $chunk = substr($pending, 0, $len & ~3);
    $pending = substr($pending, $len & ~3 + 1);

    # Easy method: translate from chars to (pregenerated) six-bit packets, join,
    # split in 8-bit chunks and convert back to char.
    print join q(),
      map $bytes{$_},
        ((join q(), map {$trans{$_} || q()} split //, $chunk) =~ /......../g);

    last if $finished;
858
}' %n"
859 860 861 862
  "Perl program to use for decoding a file.
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.")

863 864 865 866 867 868 869 870 871 872
(defconst tramp-perl-pack
  "%s -e 'binmode STDIN; binmode STDOUT; print pack(q{u*}, join q{}, <>)'"
  "Perl program to use for encoding a file.
Escape sequence %s is replaced with name of Perl binary.")

(defconst tramp-perl-unpack
  "%s -e 'binmode STDIN; binmode STDOUT; print unpack(q{u*}, join q{}, <>)'"
  "Perl program to use for decoding a file.
Escape sequence %s is replaced with name of Perl binary.")

873 874 875 876
(defconst tramp-hexdump-encode "%h -v -e '16/1 \" %%02x\" \"\\n\"'"
  "`hexdump' program to use for encoding a file.
This string is passed to `format', so percent characters need to be doubled.")

877
(defconst tramp-awk-encode
878
  "%a '\\
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
BEGIN {
  b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"
  b16 = \"0123456789abcdef\"
}
{
  for (c=1; c<=length($0); c++) {
    d=index(b16, substr($0,c,1))
    if (d--) {
      for (b=1; b<=4; b++) {
        o=o*2+int(d/8); d=(d*2)%%16
        if (++obc==6) {
          printf substr(b64,o+1,1)
          if (++rc>75) { printf \"\\n\"; rc=0 }
          obc=0; o=0
        }
      }
    }
  }
}
END {
  if (obc) {
    tail=(obc==2) ? \"==\\n\" : \"=\\n\"
    while (obc++<6) { o=o*2 }
    printf \"%%c\", substr(b64,o+1,1)
  } else {
    tail=\"\\n\"
  }
  printf tail
}'"
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
  "`awk' program to use for encoding a file.
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-hexdump-awk-encode
  (format "%s | %s" tramp-hexdump-encode tramp-awk-encode)
  "`hexdump' / `awk' pipe to use for encoding a file.
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-od-encode "%o -v -t x1 -A n"
  "`od' program to use for encoding a file.
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-od-awk-encode
  (format "%s | %s" tramp-od-encode tramp-awk-encode)
  "`od' / `awk' pipe to use for encoding a file.
923 924 925
This string is passed to `format', so percent characters need to be doubled.")

(defconst tramp-awk-decode
926
  "%a '\\
927 928 929 930 931 932 933 934 935 936 937 938 939
BEGIN {
  b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"
}
{
  for (i=1; i<=length($0); i++) {
    c=index(b64, substr($0,i,1))
    if(c--) {
      for(b=0; b<6; b++) {
        o=o*2+int(c/32); c=(c*2)%%64
        if(++obc==8) {
          if (o) {
            printf \"%%c\", o
          } else {
940
            system(\"dd if=/dev/zero bs=1 count=1 %n\")
941 942 943 944 945 946 947 948 949 950
          }
          obc=0; o=0
        }
      }
    }
  }
}'"
  "Awk program to use for decoding a file.
This string is passed to `format', so percent characters need to be doubled.")

951 952 953
(defconst tramp-vc-registered-read-file-names
  "echo \"(\"
while read file; do
Michael Albinus's avatar
Michael Albinus committed
954
    quoted=`echo \"$file\" | sed -e \"s/\\\"/\\\\\\\\\\\\\\\\\\\"/\"`
955
    if %s \"$file\"; then
Michael Albinus's avatar
Michael Albinus committed
956
	echo \"(\\\"$quoted\\\" \\\"file-exists-p\\\" t)\"
957
    else
Michael Albinus's avatar
Michael Albinus committed
958
	echo \"(\\\"$quoted\\\" \\\"file-exists-p\\\" nil)\"
959 960
    fi
    if %s \"$file\"; then
Michael Albinus's avatar
Michael Albinus committed
961
	echo \"(\\\"$quoted\\\" \\\"file-readable-p\\\" t)\"
962
    else
Michael Albinus's avatar
Michael Albinus committed
963
	echo \"(\\\"$quoted\\\" \\\"file-readable-p\\\" nil)\"
964 965 966 967 968 969 970 971 972
    fi
done
echo \")\""
  "Script to check existence of VC related files.
It must be send formatted with two strings; the tests for file
existence, and file readability.  Input shall be read via
here-document, otherwise the command could exceed maximum length
of command line.")

Michael Albinus's avatar
Michael Albinus committed
973
;; New handlers should be added here.
Michael Albinus's avatar
Michael Albinus committed
974
;;;###tramp-autoload
975
(defconst tramp-sh-file-name-handler-alist
976
  '((access-file . tramp-handle-access-file)
977
    (add-name-to-file . tramp-sh-handle-add-name-to-file)
Michael Albinus's avatar
Michael Albinus committed
978
    ;; `byte-compiler-base-file-name' performed by default handler.
979
    (copy-directory . tramp-sh-handle-copy-directory)
Michael Albinus's avatar
Michael Albinus committed
980
    (copy-file . tramp-sh-handle-copy-file)
981 982
    (delete-directory . tramp-sh-handle-delete-directory)
    (delete-file . tramp-sh-handle-delete-file)
Michael Albinus's avatar
Michael Albinus committed
983
    ;; `diff-latest-backup-file' performed by default handler.
984
    (directory-file-name . tramp-handle-directory-file-name)
Michael Albinus's avatar
Michael Albinus committed
985 986 987 988 989
    (directory-files . tramp-handle-directory-files)
    (directory-files-and-attributes
     . tramp-sh-handle-directory-files-and-attributes)
    (dired-compress-file . tramp-sh-handle-dired-compress-file)
    (dired-uncache . tramp-handle-dired-uncache)
990
    (exec-path . tramp-sh-handle-exec-path)
991
    (expand-file-name . tramp-sh-handle-expand-file-name)
Michael Albinus's avatar
Michael Albinus committed
992 993 994 995
    (file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
    (file-acl . tramp-sh-handle-file-acl)
    (file-attributes . tramp-sh-handle-file-attributes)
    (file-directory-p . tramp-sh-handle-file-directory-p)
996
    (file-equal-p . tramp-handle-file-equal-p)
Michael Albinus's avatar
Michael Albinus committed
997 998
    (file-executable-p . tramp-sh-handle-file-executable-p)
    (file-exists-p . tramp-sh-handle-file-exists-p)
999
    (file-in-directory-p . tramp-handle-file-in-directory-p)
1000
    (file-local-copy . tramp-sh-handle-file-local-copy)
Michael Albinus's avatar
Michael Albinus committed
1001 1002 1003
    (file-modes . tramp-handle-file-modes)
    (file-name-all-completions . tramp-sh-handle-file-name-all-completions)
    (file-name-as-directory . tramp-handle-file-name-as-directory)
1004
    (file-name-case-insensitive-p . tramp-handle-file-name-case-insensitive-p)
Michael Albinus's avatar
Michael Albinus committed
1005 1006 1007 1008 1009 1010 1011
    (file-name-completion . tramp-handle-file-name-completion)
    (file-name-directory . tramp-handle-file-name-directory)
    (file-name-nondirectory . tramp-handle-file-name-nondirectory)
    ;; `file-name-sans-versions' performed by default handler.
    (file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p)
    (file-notify-add-watch . tramp-sh-handle-file-notify-add-watch)
    (file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
1012
    (file-notify-valid-p . tramp-handle-file-notify-valid-p)
Michael Albinus's avatar
Michael Albinus committed
1013 1014 1015
    (file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p)
    (file-readable-p . tramp-sh-handle-file-readable-p)
    (file-regular-p . tramp-handle-file-regular-p)
1016
    (file-remote-p . tramp-handle-file-remote-p)
Michael Albinus's avatar
Michael Albinus committed
1017 1018
    (file-selinux-context . tramp-sh-handle-file-selinux-context)
    (file-symlink-p . tramp-handle-file-symlink-p)
1019
    (file-system-info . tramp-sh-handle-file-system-info)
Michael Albinus's avatar
Michael Albinus committed
1020 1021 1022 1023 1024
    (file-truename . tramp-sh-handle-file-truename)
    (file-writable-p . tramp-sh-handle-file-writable-p)
    (find-backup-file-name . tramp-handle-find-backup-file-name)
    ;; `get-file-buffer' performed by default handler.
    (insert-directory . tramp-sh-handle-insert-directory)
1025
    (insert-file-contents . tramp-handle-insert-file-contents)
Michael Albinus's avatar
Michael Albinus committed
1026
    (load . tramp-handle-load)
1027
    (make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
Michael Albinus's avatar
Michael Albinus committed
1028
    (make-directory . tramp-sh-handle-make-directory)
Michael Albinus's avatar
Michael Albinus committed
1029
    ;; `make-directory-internal' performed by default handler.
1030
    (make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
1031
    (make-process . tramp-sh-handle-make-process)
Michael Albinus's avatar
Michael Albinus committed
1032 1033 1034
    (make-symbolic-link . tramp-sh-handle-make-symbolic-link)
    (process-file . tramp-sh-handle-process-file)
    (rename-file . tramp-sh-handle-rename-file)
1035
    (set-file-acl . tramp-sh-handle-set-file-acl)
Michael Albinus's avatar
Michael Albinus committed
1036 1037 1038 1039 1040
    (set-file-modes . tramp-sh-handle-set-file-modes)
    (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
    (set-file-times . tramp-sh-handle-set-file-times)
    (set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime)
    (shell-command . tramp-handle-shell-command)
1041
    (start-file-process . tramp-handle-start-file-process)
Michael Albinus's avatar
Michael Albinus committed
1042
    (substitute-in-file-name . tramp-handle-substitute-in-file-name)
1043
    (temporary-file-directory . tramp-handle-temporary-file-directory)
1044 1045
    (tramp-get-remote-gid . tramp-sh-handle-get-remote-gid)
    (tramp-get-remote-uid . tramp-sh-handle-get-remote-uid)
Michael Albinus's avatar
Michael Albinus committed
1046
    (tramp-set-file-uid-gid . tramp-sh-handle-set-file-uid-gid)
1047
    (unhandled-file-name-directory . ignore)
1048
    (vc-registered . tramp-sh-handle-vc-registered)
Michael Albinus's avatar
Michael Albinus committed
1049 1050
    (verify-visited-file-modtime . tramp-sh-handle-verify-visited-file-modtime)
    (write-region . tramp-sh-handle-write-region))
1051 1052 1053 1054 1055
  "Alist of handler functions.
Operations not mentioned here will be handled by the normal Emacs functions.")

;;; File Name Handler Functions:

1056
(defun tramp-sh-handle-make-symbolic-link
Michael Albinus's avatar
Michael Albinus committed
1057
    (target linkname &optional ok-if-already-exists)
1058
  "Like `make-symbolic-link' for Tramp files.
Michael Albinus's avatar
Michael Albinus committed
1059 1060 1061 1062 1063
If TARGET is a non-Tramp file, it is used verbatim as the target
of the symlink.  If TARGET is a Tramp file, only the localname
component is used as the target of the symlink."
  (if (not (tramp-tramp-file-p (expand-file-name linkname)))
      (tramp-run-real-handler
1064
       #'make-symbolic-link (list target linkname ok-if-already-exists))
Michael Albinus's avatar
Michael Albinus committed
1065 1066

    (with-parsed-tramp-file-name linkname nil
1067
      ;; If TARGET is a Tramp name, use just the localname component.
1068 1069 1070 1071
      ;; Don't check for a proper method.
      (let ((non-essential t))
	(when (and (tramp-tramp-file-p target)
		   (tramp-file-name-equal-p v (tramp-dissect-file-name target)))
Michael Albinus's avatar
Michael Albinus committed
1072
	  (setq target (tramp-file-local-name (expand-file-name target)))))
1073 1074 1075

      ;; If TARGET is still remote, quote it.
      (if (tramp-tramp-file-p target)
1076
	  (make-symbolic-link (tramp-compat-file-name-quote target 'top)
1077 1078 1079 1080
	   linkname ok-if-already-exists)

	(let ((ln (tramp-get-remote-ln v))
	      (cwd (tramp-run-real-handler
1081
		    #'file-name-directory (list localname))))
1082 1083 1084
	  (unless ln
	    (tramp-error
	     v 'file-error
Michael Albinus's avatar
Michael Albinus committed
1085 1086
	   "Making a symbolic link.  ln(1) does not exist on the remote host."))

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
	  ;; Do the 'confirm if exists' thing.
	  (when (file-exists-p linkname)
	    ;; What to do?
	    (if (or (null ok-if-already-exists) ; not allowed to exist
		    (and (numberp ok-if-already-exists)
			 (not
			  (yes-or-no-p
			   (format
			    "File %s already exists; make it a link anyway? "
			    localname)))))
		(tramp-error v 'file-already-exists localname)
	      (delete-file linkname)))

1100
	  (tramp-flush-file-properties v localname)