93 |
93 |
94 def open_session( |
94 def open_session( |
95 options: Options, |
95 options: Options, |
96 host: String, |
96 host: String, |
97 port: Int = 0, |
97 port: Int = 0, |
98 user: String = "" |
98 user: String = "", |
|
99 user_home: String = "" |
99 ): Session = { |
100 ): Session = { |
100 if (is_local(host)) error("Illegal SSH host name " + quote(host)) |
101 if (is_local(host)) error("Illegal SSH host name " + quote(host)) |
101 |
102 |
102 val multiplex = options.bool("ssh_multiplexing") && !Platform.is_windows |
103 val multiplex = options.bool("ssh_multiplexing") && !Platform.is_windows |
103 val (control_master, control_path) = |
104 val (control_master, control_path) = |
104 if (multiplex) (true, Isabelle_System.tmp_file("ssh", initialized = false).getPath) |
105 if (multiplex) (true, Isabelle_System.tmp_file("ssh", initialized = false).getPath) |
105 else (false, "") |
106 else (false, "") |
106 new Session(options, host, port, user, control_master, control_path) |
107 new Session(options, host, port, user, user_home, control_master, control_path) |
107 } |
108 } |
108 |
109 |
109 class Session private[SSH]( |
110 class Session private[SSH]( |
110 val options: Options, |
111 val options: Options, |
111 val host: String, |
112 val host: String, |
112 val port: Int, |
113 val port: Int, |
113 val user: String, |
114 val user: String, |
|
115 user_home0: String, |
114 control_master: Boolean, |
116 control_master: Boolean, |
115 val control_path: String |
117 val control_path: String |
116 ) extends System { |
118 ) extends System { |
117 ssh => |
119 ssh => |
118 |
120 |
176 } |
178 } |
177 |
179 |
178 |
180 |
179 /* init and exit */ |
181 /* init and exit */ |
180 |
182 |
181 val user_home: String = { |
183 override val home: String = { |
182 run_ssh(master = control_master, args = "printenv HOME \";\" printenv SHELL").check.out_lines |
184 run_ssh(master = control_master, args = "printenv HOME \";\" printenv SHELL").check.out_lines |
183 match { |
185 match { |
184 case List(user_home, shell) => |
186 case List(home, shell) => |
185 if (shell.endsWith("/bash")) user_home |
187 if (shell.endsWith("/bash")) home |
186 else { |
188 else { |
187 error("Bad SHELL for " + quote(toString) + " -- expected GNU bash, but found " + shell) |
189 error("Bad SHELL for " + quote(toString) + " -- expected GNU bash, but found " + shell) |
188 } |
190 } |
189 case _ => error("Malformed remote environment for " + quote(toString)) |
191 case _ => error("Malformed remote environment for " + quote(toString)) |
190 } |
192 } |
191 } |
193 } |
192 |
194 |
193 val settings: Isabelle_System.Settings = |
195 override val user_home: String = { |
194 (name: String) => if (name == "HOME" || name == "USER_HOME") user_home else "" |
196 val path1 = |
|
197 try { Path.explode(home).expand_env(Isabelle_System.No_Env) } |
|
198 catch { case ERROR(msg) => error(msg + " -- in SSH HOME") } |
|
199 val path2 = |
|
200 try { Path.explode(user_home0).expand_env(Isabelle_System.No_Env) } |
|
201 catch { case ERROR(msg) => error(msg + "-- in SSH USER_HOME") } |
|
202 (path1 + path2).implode |
|
203 } |
|
204 |
|
205 val settings: Isabelle_System.Settings = { |
|
206 case "HOME" => home |
|
207 case "USER_HOME" => user_home |
|
208 case _ => "" |
|
209 } |
195 |
210 |
196 override def close(): Unit = { |
211 override def close(): Unit = { |
197 if (control_path.nonEmpty) run_ssh(opts = "-O exit").check |
212 if (control_path.nonEmpty) run_ssh(opts = "-O exit").check |
198 } |
213 } |
199 |
214 |
205 progress_stderr: String => Unit = (_: String) => (), |
220 progress_stderr: String => Unit = (_: String) => (), |
206 redirect: Boolean = false, |
221 redirect: Boolean = false, |
207 settings: Boolean = true, |
222 settings: Boolean = true, |
208 strict: Boolean = true |
223 strict: Boolean = true |
209 ): Process_Result = { |
224 ): Process_Result = { |
|
225 val script = Isabelle_System.export_env(user_home = user_home) + cmd_line |
210 run_command("ssh", |
226 run_command("ssh", |
211 args = Bash.string(host) + " " + Bash.string(cmd_line), |
227 args = Bash.string(host) + " " + Bash.string(script), |
212 progress_stdout = progress_stdout, |
228 progress_stdout = progress_stdout, |
213 progress_stderr = progress_stderr, |
229 progress_stderr = progress_stderr, |
214 redirect = redirect, |
230 redirect = redirect, |
215 strict = strict) |
231 strict = strict) |
216 } |
232 } |
234 /* remote file-system */ |
250 /* remote file-system */ |
235 |
251 |
236 override def expand_path(path: Path): Path = path.expand_env(settings) |
252 override def expand_path(path: Path): Path = path.expand_env(settings) |
237 override def absolute_path(path: Path): Path = { |
253 override def absolute_path(path: Path): Path = { |
238 val path1 = expand_path(path) |
254 val path1 = expand_path(path) |
239 if (path1.is_absolute) path1 else Path.explode(user_home) + path1 |
255 if (path1.is_absolute) path1 else Path.explode(home) + path1 |
240 } |
256 } |
241 |
257 |
242 def remote_path(path: Path): String = expand_path(path).implode |
258 def remote_path(path: Path): String = expand_path(path).implode |
243 |
259 |
244 override def bash_path(path: Path): String = Bash.string(remote_path(path)) |
260 override def bash_path(path: Path): String = Bash.string(remote_path(path)) |
385 def open_server( |
401 def open_server( |
386 options: Options, |
402 options: Options, |
387 host: String, |
403 host: String, |
388 port: Int = 0, |
404 port: Int = 0, |
389 user: String = "", |
405 user: String = "", |
|
406 user_home: String = "", |
390 remote_port: Int = 0, |
407 remote_port: Int = 0, |
391 remote_host: String = "localhost", |
408 remote_host: String = "localhost", |
392 local_port: Int = 0, |
409 local_port: Int = 0, |
393 local_host: String = "localhost" |
410 local_host: String = "localhost" |
394 ): Server = { |
411 ): Server = { |
395 val ssh = open_session(options, host, port = port, user = user) |
412 val ssh = open_session(options, host, port = port, user = user, user_home = user_home) |
396 try { |
413 try { |
397 ssh.open_server(remote_port = remote_port, remote_host = remote_host, |
414 ssh.open_server(remote_port = remote_port, remote_host = remote_host, |
398 local_port = local_port, local_host = local_host, ssh_close = true) |
415 local_port = local_port, local_host = local_host, ssh_close = true) |
399 } |
416 } |
400 catch { case exn: Throwable => ssh.close(); throw exn } |
417 catch { case exn: Throwable => ssh.close(); throw exn } |
428 |
445 |
429 def open_system( |
446 def open_system( |
430 options: Options, |
447 options: Options, |
431 host: String, |
448 host: String, |
432 port: Int = 0, |
449 port: Int = 0, |
433 user: String = "" |
450 user: String = "", |
|
451 user_home: String = "" |
434 ): System = { |
452 ): System = { |
435 if (is_local(host)) Local |
453 if (is_local(host)) Local |
436 else open_session(options, host = host, port = port, user = user) |
454 else open_session(options, host = host, port = port, user = user, user_home = user_home) |
437 } |
455 } |
438 |
456 |
439 trait System extends AutoCloseable { |
457 trait System extends AutoCloseable { |
440 def ssh_session: Option[Session] |
458 def ssh_session: Option[Session] |
441 def is_local: Boolean = ssh_session.isEmpty |
459 def is_local: Boolean = ssh_session.isEmpty |
|
460 |
|
461 def home: String = "" |
|
462 def user_home: String = "" |
442 |
463 |
443 def close(): Unit = () |
464 def close(): Unit = () |
444 |
465 |
445 override def toString: String = LOCAL |
466 override def toString: String = LOCAL |
446 def print: String = "" |
467 def print: String = "" |