1
+ use crate :: escape;
2
+
1
3
use super :: stdio:: TryFromChildIo ;
2
4
use super :: RemoteChild ;
3
5
use super :: Stdio ;
4
6
use super :: { Error , Session } ;
5
7
6
8
use std:: borrow:: Cow ;
7
9
use std:: ffi:: OsStr ;
10
+ use std:: os:: unix:: prelude:: OsStrExt ;
8
11
use std:: process;
9
12
10
13
#[ derive( Debug ) ]
@@ -57,15 +60,10 @@ pub trait OverSsh {
57
60
/// **Note**: The command to be executed on the remote machine does not include
58
61
/// any environment variables or the current directory. They must be
59
62
/// set explicitly, if desired.
60
- fn over_session < ' session > ( & self , session : & ' session Session ) -> crate :: Command < ' session > ;
61
- }
62
-
63
- impl OverSsh for std:: process:: Command {
64
- /// Given a session, convert a `std::process::Command` into an `openssh::Command`
65
- /// that can be executed over that session.
66
- /// **Note**: The command to be executed on the remote machine does not include
67
- /// any environment variables or the current directory. They must be
68
- /// set explicitly, if desired.
63
+ ///
64
+ /// # Example
65
+ /// Consider the implementation of `OverSsh` for `std::process::Command`:
66
+ ///
69
67
/// ```no_run
70
68
/// # #[tokio::main(flavor = "current_thread")]
71
69
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -87,42 +85,26 @@ impl OverSsh for std::process::Command {
87
85
/// }
88
86
///
89
87
/// ```
88
+ fn over_session < ' session > ( & self , session : & ' session Session ) -> crate :: Command < ' session > ;
89
+ }
90
+
91
+ impl OverSsh for std:: process:: Command {
90
92
fn over_session < ' session > ( & self , session : & ' session Session ) -> Command < ' session > {
91
- let mut command = session. command ( self . get_program ( ) . to_string_lossy ( ) ) ;
92
- command. raw_args ( self . get_args ( ) ) ;
93
+ let program_escaped = escape ( self . get_program ( ) . as_bytes ( ) ) ;
94
+ let mut command = session. command ( Cow :: Borrowed ( program_escaped. as_str ( ) ) ) ;
95
+
96
+ self
97
+ . get_args ( )
98
+ . for_each ( |arg| {
99
+ let arg_escaped = escape ( arg. as_bytes ( ) ) ;
100
+ command. arg ( Cow :: Borrowed ( arg_escaped. as_str ( ) ) ) ;
101
+ } ) ;
93
102
command
94
103
}
95
104
}
96
105
97
106
98
107
impl OverSsh for tokio:: process:: Command {
99
- /// Given a session, convert a `tokio::process::Command` into an `openssh::Command`
100
- /// that can be executed over that session.
101
- ///
102
- /// **Note**: The command to be executed on the remote machine does not include
103
- /// any environment variables or the current directory. They must be
104
- /// set explicitly, if desired.
105
- /// ```no_run
106
- /// # #[tokio::main(flavor = "current_thread")]
107
- /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
108
- /// use tokio::process::Command;
109
- /// use openssh::{Session, KnownHosts, OverSsh};
110
-
111
- /// let session = Session::connect_mux("me@ssh.example.com", KnownHosts::Strict).await?;
112
- /// let ls =
113
- /// Command::new("ls")
114
- /// .arg("-l")
115
- /// .arg("-a")
116
- /// .arg("-h")
117
- /// .over_session(&session)
118
- /// .output()
119
- /// .await?;
120
- ///
121
- /// assert!(String::from_utf8(ls.stdout).unwrap().contains("total"));
122
- /// # Ok(())
123
- /// # }
124
- ///
125
- /// ```
126
108
fn over_session < ' session > ( & self , session : & ' session Session ) -> Command < ' session > {
127
109
self . as_std ( ) . over_session ( session)
128
110
}
@@ -138,15 +120,6 @@ where
138
120
}
139
121
}
140
122
141
- impl < S > OverSsh for & mut S
142
- where
143
- S : OverSsh
144
- {
145
- fn over_session < ' session > ( & self , session : & ' session Session ) -> Command < ' session > {
146
- <S as OverSsh >:: over_session ( self , session)
147
- }
148
- }
149
-
150
123
impl < S > OverSsh for Box < S >
151
124
where
152
125
S : OverSsh
0 commit comments