author | wenzelm |
Sun, 02 Oct 2022 16:26:48 +0200 | |
changeset 76240 | 30d43e9b2077 |
parent 76170 | 5912209b4fb6 |
child 76241 | aa6ce2e51e6c |
permissions | -rw-r--r-- |
64123 | 1 |
/* Title: Pure/General/ssh.scala |
2 |
Author: Makarius |
|
3 |
||
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
4 |
SSH client on OpenSSH command-line tools, preferably with connection |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
5 |
multiplexing, but this does not work on Windows. |
64123 | 6 |
*/ |
7 |
||
8 |
package isabelle |
|
9 |
||
10 |
||
73909 | 11 |
import java.util.{Map => JMap} |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
12 |
import java.io.{File => JFile} |
64123 | 13 |
|
14 |
||
75393 | 15 |
object SSH { |
76170 | 16 |
/* client command */ |
17 |
||
18 |
def client_command(port: Int = 0, control_path: String = ""): String = |
|
19 |
if (control_path.isEmpty || control_path == Bash.string(control_path)) { |
|
20 |
"ssh" + |
|
21 |
(if (port > 0) " -p " + port else "") + |
|
22 |
(if (control_path.nonEmpty) " -o ControlPath=" + control_path else "") |
|
23 |
} |
|
24 |
else error ("Malformed SSH control socket: " + quote(control_path)) |
|
25 |
||
26 |
||
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
27 |
/* OpenSSH configuration and command-line */ |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
28 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
29 |
// see https://linux.die.net/man/5/ssh_config |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
30 |
object Config { |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
31 |
def entry(x: String, y: String): String = x + "=" + y |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
32 |
def entry(x: String, y: Int): String = entry(x, y.toString) |
76165 | 33 |
def entry(x: String, y: Long): String = entry(x, y.toString) |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
34 |
def entry(x: String, y: Boolean): String = entry(x, if (y) "yes" else "no") |
64141 | 35 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
36 |
def make(options: Options, |
76131
8b695e59db3f
clarified default: do not override port from ssh_config, which could be different from 22;
wenzelm
parents:
76130
diff
changeset
|
37 |
port: Int = 0, |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
38 |
user: String = "", |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
39 |
control_master: Boolean = false, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
40 |
control_path: String = "" |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
41 |
): List[String] = { |
76168 | 42 |
val ssh_batch_mode = options.bool("ssh_batch_mode") |
76167 | 43 |
val ssh_compression = options.bool("ssh_compression") |
44 |
val ssh_alive_interval = options.real("ssh_alive_interval").round |
|
45 |
val ssh_alive_count_max = options.int("ssh_alive_count_max") |
|
46 |
||
76168 | 47 |
List( |
48 |
entry("BatchMode", ssh_batch_mode), |
|
49 |
entry("Compression", ssh_compression)) ::: |
|
76167 | 50 |
(if (ssh_alive_interval >= 0) List(entry("ServerAliveInterval", ssh_alive_interval)) else Nil) ::: |
51 |
(if (ssh_alive_count_max >= 0) List(entry("ServerAliveCountMax", ssh_alive_count_max)) else Nil) ::: |
|
76131
8b695e59db3f
clarified default: do not override port from ssh_config, which could be different from 22;
wenzelm
parents:
76130
diff
changeset
|
52 |
(if (port > 0) List(entry("Port", port)) else Nil) ::: |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
53 |
(if (user.nonEmpty) List(entry("User", user)) else Nil) ::: |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
54 |
(if (control_master) List("ControlMaster=yes", "ControlPersist=yes") else Nil) ::: |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
55 |
(if (control_path.nonEmpty) List("ControlPath=" + control_path) else Nil) |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
56 |
} |
64325 | 57 |
|
76147 | 58 |
def option(entry: String): String = "-o " + Bash.string(entry) |
59 |
def option(x: String, y: String): String = option(entry(x, y)) |
|
60 |
def option(x: String, y: Int): String = option(entry(x, y)) |
|
76165 | 61 |
def option(x: String, y: Long): String = option(entry(x, y)) |
76147 | 62 |
def option(x: String, y: Boolean): String = option(entry(x, y)) |
63 |
||
64 |
def command(command: String, config: List[String]): String = |
|
65 |
Bash.string(command) + config.map(entry => " " + option(entry)).mkString |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
66 |
} |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
67 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
68 |
def sftp_string(str: String): String = { |
76150 | 69 |
val special = "[]?*\\{} \"'" |
70 |
if (str.isEmpty) "\"\"" |
|
71 |
else if (str.exists(special.contains)) { |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
72 |
val res = new StringBuilder |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
73 |
for (c <- str) { |
76150 | 74 |
if (special.contains(c)) res += '\\' |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
75 |
res += c |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
76 |
} |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
77 |
res.toString() |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
78 |
} |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
79 |
else str |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
80 |
} |
67273
c573cfb2c407
more robust connection: prefer ServerAliveCountMax=3 (ssh default) instead of 1 (jsch default);
wenzelm
parents:
67067
diff
changeset
|
81 |
|
64123 | 82 |
|
76115
f17393e21388
clarified signature: discontinue somewhat pointless SSH.Context;
wenzelm
parents:
76100
diff
changeset
|
83 |
/* open session */ |
f17393e21388
clarified signature: discontinue somewhat pointless SSH.Context;
wenzelm
parents:
76100
diff
changeset
|
84 |
|
f17393e21388
clarified signature: discontinue somewhat pointless SSH.Context;
wenzelm
parents:
76100
diff
changeset
|
85 |
def open_session( |
f17393e21388
clarified signature: discontinue somewhat pointless SSH.Context;
wenzelm
parents:
76100
diff
changeset
|
86 |
options: Options, |
f17393e21388
clarified signature: discontinue somewhat pointless SSH.Context;
wenzelm
parents:
76100
diff
changeset
|
87 |
host: String, |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
88 |
port: Int = 0, |
76148
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
89 |
user: String = "" |
76115
f17393e21388
clarified signature: discontinue somewhat pointless SSH.Context;
wenzelm
parents:
76100
diff
changeset
|
90 |
): Session = { |
76148
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
91 |
val multiplex = options.bool("ssh_multiplexing") && !Platform.is_windows |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
92 |
val (control_master, control_path) = |
76161 | 93 |
if (multiplex) (true, Isabelle_System.tmp_file("ssh", initialized = false).getPath) |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
94 |
else (false, "") |
76131
8b695e59db3f
clarified default: do not override port from ssh_config, which could be different from 22;
wenzelm
parents:
76130
diff
changeset
|
95 |
new Session(options, host, port, user, control_master, control_path) |
64257 | 96 |
} |
64130 | 97 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
98 |
class Session private[SSH]( |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
99 |
val options: Options, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
100 |
val host: String, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
101 |
val port: Int, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
102 |
val user: String, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
103 |
control_master: Boolean, |
76136
1bb677cceea4
let rsync re-use ssh connection via control path;
wenzelm
parents:
76133
diff
changeset
|
104 |
val control_path: String |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
105 |
) extends System { |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
106 |
ssh => |
64128 | 107 |
|
76133 | 108 |
def port_suffix: String = if (port > 0) ":" + port else "" |
109 |
def user_prefix: String = if (user.nonEmpty) user + "@" else "" |
|
110 |
||
111 |
override def toString: String = user_prefix + host + port_suffix |
|
76132 | 112 |
override def hg_url: String = "ssh://" + toString + "/" |
76133 | 113 |
override def rsync_prefix: String = user_prefix + host + ":" |
64191 | 114 |
|
115 |
||
76147 | 116 |
/* local ssh commands */ |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
117 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
118 |
def run_command(command: String, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
119 |
master: Boolean = false, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
120 |
opts: String = "", |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
121 |
args: String = "", |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
122 |
cwd: JFile = null, |
64134
57581e4026fe
proper support for exec channel (see also bash.scala);
wenzelm
parents:
64133
diff
changeset
|
123 |
progress_stdout: String => Unit = (_: String) => (), |
57581e4026fe
proper support for exec channel (see also bash.scala);
wenzelm
parents:
64133
diff
changeset
|
124 |
progress_stderr: String => Unit = (_: String) => (), |
75393 | 125 |
strict: Boolean = true |
126 |
): Process_Result = { |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
127 |
val config = |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
128 |
Config.make(options, port = port, user = user, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
129 |
control_master = master, control_path = control_path) |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
130 |
val cmd = |
76147 | 131 |
Config.command(command, config) + |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
132 |
(if (opts.nonEmpty) " " + opts else "") + |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
133 |
(if (args.nonEmpty) " -- " + args else "") |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
134 |
Isabelle_System.bash(cmd, cwd = cwd, progress_stdout = progress_stdout, |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
135 |
progress_stderr = progress_stderr, strict = strict) |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
136 |
} |
64134
57581e4026fe
proper support for exec channel (see also bash.scala);
wenzelm
parents:
64133
diff
changeset
|
137 |
|
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
138 |
def run_sftp( |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
139 |
script: String, |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
140 |
init: Path => Unit = _ => (), |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
141 |
exit: Path => Unit = _ => () |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
142 |
): Process_Result = { |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
143 |
Isabelle_System.with_tmp_dir("ssh") { dir => |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
144 |
init(dir) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
145 |
File.write(dir + Path.explode("script"), script) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
146 |
val result = |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
147 |
run_command("sftp", opts = "-b script", args = Bash.string(host), cwd = dir.file).check |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
148 |
exit(dir) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
149 |
result |
76116
c4dc343fdbcb
clarified signature: avoid exposure of JSch types;
wenzelm
parents:
76115
diff
changeset
|
150 |
} |
c4dc343fdbcb
clarified signature: avoid exposure of JSch types;
wenzelm
parents:
76115
diff
changeset
|
151 |
} |
65009 | 152 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
153 |
def run_ssh(master: Boolean = false, opts: String = "", args: String = ""): Process_Result = { |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
154 |
val args1 = Bash.string(host) + (if (args.nonEmpty) " " + args else "") |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
155 |
run_command("ssh", master = master, opts = opts, args = args1) |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
156 |
} |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
157 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
158 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
159 |
/* init and exit */ |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
160 |
|
76151 | 161 |
val user_home: String = { |
76154
dfddb80fc515
more robust: do not assume Bash syntax while testing for it;
wenzelm
parents:
76151
diff
changeset
|
162 |
run_ssh(master = control_master, args = "printenv HOME \";\" printenv SHELL").check.out_lines |
dfddb80fc515
more robust: do not assume Bash syntax while testing for it;
wenzelm
parents:
76151
diff
changeset
|
163 |
match { |
76149
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
164 |
case List(user_home, shell) => |
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
165 |
if (shell.endsWith("/bash")) user_home |
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
166 |
else { |
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
167 |
error("Bad SHELL for " + quote(toString) + " -- expected GNU bash, but found " + shell) |
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
168 |
} |
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
169 |
case _ => error("Malformed remote environment for " + quote(toString)) |
ccc748255342
more robust: Bash.string operations require remote bash;
wenzelm
parents:
76148
diff
changeset
|
170 |
} |
76151 | 171 |
} |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
172 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
173 |
val settings: JMap[String, String] = JMap.of("HOME", user_home, "USER_HOME", user_home) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
174 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
175 |
override def close(): Unit = { |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
176 |
if (control_path.nonEmpty) run_ssh(opts = "-O exit").check |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
177 |
} |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
178 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
179 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
180 |
/* remote commands */ |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
181 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
182 |
override def execute(cmd_line: String, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
183 |
progress_stdout: String => Unit = (_: String) => (), |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
184 |
progress_stderr: String => Unit = (_: String) => (), |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
185 |
settings: Boolean = true, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
186 |
strict: Boolean = true |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
187 |
): Process_Result = { |
76151 | 188 |
val args1 = Bash.string(host) + " " + Bash.string("export USER_HOME=\"$HOME\"\n" + cmd_line) |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
189 |
run_command("ssh", args = args1, progress_stdout = progress_stdout, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
190 |
progress_stderr = progress_stderr, strict = strict) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
191 |
} |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
192 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
193 |
override lazy val isabelle_platform: Isabelle_Platform = Isabelle_Platform(ssh = Some(ssh)) |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
194 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
195 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
196 |
/* remote file-system */ |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
197 |
|
66570 | 198 |
override def expand_path(path: Path): Path = path.expand_env(settings) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
199 |
def remote_path(path: Path): String = expand_path(path).implode |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
200 |
|
67066 | 201 |
override def bash_path(path: Path): String = Bash.string(remote_path(path)) |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
202 |
def sftp_path(path: Path): String = sftp_string(remote_path(path)) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
203 |
|
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
204 |
def rm(path: Path): Unit = run_sftp("rm " + sftp_path(path)) |
69300
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
wenzelm
parents:
67771
diff
changeset
|
205 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
206 |
override def is_dir(path: Path): Boolean = run_ssh(args = "test -d " + bash_path(path)).ok |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
207 |
override def is_file(path: Path): Boolean = run_ssh(args = "test -f " + bash_path(path)).ok |
69300
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
wenzelm
parents:
67771
diff
changeset
|
208 |
|
75393 | 209 |
override def make_directory(path: Path): Path = { |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
210 |
if (!execute("mkdir -p " + bash_path(path)).ok) { |
76118 | 211 |
error("Failed to create directory: " + quote(remote_path(path))) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
212 |
} |
72376 | 213 |
path |
214 |
} |
|
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
215 |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
216 |
def read_dir(path: Path): List[String] = |
76240 | 217 |
run_sftp("@ls -1 -a " + sftp_path(path)).out_lines.flatMap(s => |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
218 |
if (s == "." || s == ".." || s.endsWith("/.") || s.endsWith("/..")) None |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
219 |
else Some(Library.perhaps_unprefix("./", s))) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
220 |
|
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
221 |
private def get_file[A](path: Path, f: Path => A): A = { |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
222 |
var result: Option[A] = None |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
223 |
run_sftp("get -p " + sftp_path(path) + " local", |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
224 |
exit = dir => result = Some(f(dir + Path.explode("local")))) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
225 |
result.get |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
226 |
} |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
227 |
|
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
228 |
private def put_file(path: Path, f: Path => Unit): Unit = |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
229 |
run_sftp("put -p local " + sftp_path(path), |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
230 |
init = dir => f(dir + Path.explode("local"))) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
231 |
|
73634 | 232 |
override def read_file(path: Path, local_path: Path): Unit = |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
233 |
get_file(path, Isabelle_System.copy_file(_, local_path)) |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
234 |
override def read_bytes(path: Path): Bytes = |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
235 |
get_file(path, Bytes.read) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
236 |
override def read(path: Path): String = |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
237 |
get_file(path, File.read) |
64256
c3197aeae90b
simplified SSH.Session: sftp channel is always open and its operations provided by the main interface;
wenzelm
parents:
64254
diff
changeset
|
238 |
|
73634 | 239 |
override def write_file(path: Path, local_path: Path): Unit = |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
240 |
put_file(path, Isabelle_System.copy_file(local_path, _)) |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
241 |
def write_bytes(path: Path, bytes: Bytes): Unit = |
76164
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
242 |
put_file(path, Bytes.write(_, bytes)) |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
243 |
def write(path: Path, text: String): Unit = |
5e8bc80df6b3
clarified run_sftp: avoid platform_path via careful use of tmp_dir, to support both Windows and Cygwin ssh;
wenzelm
parents:
76163
diff
changeset
|
244 |
put_file(path, File.write(_, text)) |
72338 | 245 |
|
64137 | 246 |
|
247 |
/* tmp dirs */ |
|
248 |
||
64306
7b6dc1b36f20
tuned signature, in accordance to Isabelle_System;
wenzelm
parents:
64304
diff
changeset
|
249 |
def rm_tree(dir: Path): Unit = rm_tree(remote_path(dir)) |
7b6dc1b36f20
tuned signature, in accordance to Isabelle_System;
wenzelm
parents:
64304
diff
changeset
|
250 |
|
64137 | 251 |
def rm_tree(remote_dir: String): Unit = |
64304 | 252 |
execute("rm -r -f " + Bash.string(remote_dir)).check |
64137 | 253 |
|
254 |
def tmp_dir(): String = |
|
76163
9df6f51ebf45
more robust, notably for macOS (see also ff92d6edff2c);
wenzelm
parents:
76161
diff
changeset
|
255 |
execute("mktemp -d /tmp/ssh-XXXXXXXXXXXX").check.out |
64137 | 256 |
|
75393 | 257 |
override def with_tmp_dir[A](body: Path => A): A = { |
64137 | 258 |
val remote_dir = tmp_dir() |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
259 |
try { body(Path.explode(remote_dir)) } |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
260 |
finally { rm_tree(remote_dir) } |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
261 |
} |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
262 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
263 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
264 |
/* port forwarding */ |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
265 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
266 |
def port_forwarding( |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
267 |
remote_port: Int, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
268 |
remote_host: String = "localhost", |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
269 |
local_port: Int = 0, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
270 |
local_host: String = "localhost", |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
271 |
ssh_close: Boolean = false |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
272 |
): Port_Forwarding = { |
76145 | 273 |
val port = if (local_port > 0) local_port else Isabelle_System.local_port() |
274 |
||
76147 | 275 |
val forward = List(local_host, port, remote_host, remote_port).mkString(":") |
276 |
val forward_option = "-L " + Bash.string(forward) |
|
277 |
||
278 |
val cancel: () => Unit = |
|
279 |
if (control_path.nonEmpty) { |
|
280 |
run_ssh(opts = forward_option + " -O forward").check |
|
281 |
() => run_ssh(opts = forward_option + " -O cancel") // permissive |
|
282 |
} |
|
76148
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
283 |
else { |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
284 |
val result = Synchronized[Exn.Result[Boolean]](Exn.Res(false)) |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
285 |
val thread = Isabelle_Thread.fork("port_forwarding") { |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
286 |
val opts = |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
287 |
forward_option + |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
288 |
" " + Config.option("SessionType", "none") + |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
289 |
" " + Config.option("PermitLocalCommand", true) + |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
290 |
" " + Config.option("LocalCommand", "pwd") |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
291 |
try { |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
292 |
run_command("ssh", opts = opts, args = Bash.string(host), |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
293 |
progress_stdout = _ => result.change(_ => Exn.Res(true))).check |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
294 |
} |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
295 |
catch { case exn: Throwable => result.change(_ => Exn.Exn(exn)) } |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
296 |
} |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
297 |
result.guarded_access { |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
298 |
case res@Exn.Res(ok) => if (ok) Some((), res) else None |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
299 |
case Exn.Exn(exn) => throw exn |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
300 |
} |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
301 |
() => thread.interrupt() |
769ebb139a32
support port forwarding without multiplexing (for the sake of Windows);
wenzelm
parents:
76147
diff
changeset
|
302 |
} |
76147 | 303 |
|
304 |
val shutdown_hook = |
|
305 |
Isabelle_System.create_shutdown_hook { cancel() } |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
306 |
|
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
307 |
new Port_Forwarding(host, port, remote_host, remote_port) { |
76147 | 308 |
override def toString: String = forward |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
309 |
override def close(): Unit = { |
76147 | 310 |
cancel() |
311 |
Isabelle_System.remove_shutdown_hook(shutdown_hook) |
|
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
312 |
if (ssh_close) ssh.close() |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
313 |
} |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
314 |
} |
64137 | 315 |
} |
64123 | 316 |
} |
66570 | 317 |
|
76116
c4dc343fdbcb
clarified signature: avoid exposure of JSch types;
wenzelm
parents:
76115
diff
changeset
|
318 |
abstract class Port_Forwarding private[SSH]( |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
319 |
val host: String, |
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
320 |
val port: Int, |
76116
c4dc343fdbcb
clarified signature: avoid exposure of JSch types;
wenzelm
parents:
76115
diff
changeset
|
321 |
val remote_host: String, |
c4dc343fdbcb
clarified signature: avoid exposure of JSch types;
wenzelm
parents:
76115
diff
changeset
|
322 |
val remote_port: Int |
76122
b8f26c20d3b1
ssh client via regular OpenSSH tools, with authentic use of .ssh/config (notably proxy configuration);
wenzelm
parents:
76119
diff
changeset
|
323 |
) extends AutoCloseable |
76116
c4dc343fdbcb
clarified signature: avoid exposure of JSch types;
wenzelm
parents:
76115
diff
changeset
|
324 |
|
66570 | 325 |
|
326 |
/* system operations */ |
|
327 |
||
75393 | 328 |
trait System extends AutoCloseable { |
73634 | 329 |
def close(): Unit = () |
330 |
||
66570 | 331 |
def hg_url: String = "" |
332 |
||
75500 | 333 |
def rsync_prefix: String = "" |
75517 | 334 |
def rsync_path(path: Path): String = rsync_prefix + expand_path(path).implode |
75500 | 335 |
|
66570 | 336 |
def expand_path(path: Path): Path = path.expand |
67066 | 337 |
def bash_path(path: Path): String = File.bash_path(path) |
69300
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
wenzelm
parents:
67771
diff
changeset
|
338 |
def is_dir(path: Path): Boolean = path.is_dir |
66570 | 339 |
def is_file(path: Path): Boolean = path.is_file |
72376 | 340 |
def make_directory(path: Path): Path = Isabelle_System.make_directory(path) |
73634 | 341 |
def with_tmp_dir[A](body: Path => A): A = Isabelle_System.with_tmp_dir("tmp")(body) |
342 |
def read_file(path1: Path, path2: Path): Unit = Isabelle_System.copy_file(path1, path2) |
|
343 |
def write_file(path1: Path, path2: Path): Unit = Isabelle_System.copy_file(path2, path1) |
|
75513 | 344 |
def read_bytes(path: Path): Bytes = Bytes.read(path) |
345 |
def read(path: Path): String = File.read(path) |
|
66570 | 346 |
|
347 |
def execute(command: String, |
|
348 |
progress_stdout: String => Unit = (_: String) => (), |
|
349 |
progress_stderr: String => Unit = (_: String) => (), |
|
73634 | 350 |
settings: Boolean = true, |
66570 | 351 |
strict: Boolean = true): Process_Result = |
73634 | 352 |
Isabelle_System.bash(command, |
353 |
progress_stdout = progress_stdout, |
|
354 |
progress_stderr = progress_stderr, |
|
355 |
env = if (settings) Isabelle_System.settings() else null, |
|
356 |
strict = strict) |
|
72338 | 357 |
|
72340 | 358 |
def isabelle_platform: Isabelle_Platform = Isabelle_Platform() |
66570 | 359 |
} |
360 |
||
361 |
object Local extends System |
|
64123 | 362 |
} |