1cc290419Sopenharmony_ci/*
2cc290419Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License.
5cc290419Sopenharmony_ci * You may obtain a copy of the License at
6cc290419Sopenharmony_ci *
7cc290419Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cc290419Sopenharmony_ci *
9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and
13cc290419Sopenharmony_ci * limitations under the License.
14cc290419Sopenharmony_ci */
15cc290419Sopenharmony_ci//! shell
16cc290419Sopenharmony_ci#![allow(missing_docs)]
17cc290419Sopenharmony_ci
18cc290419Sopenharmony_ci#[allow(unused_imports)]
19cc290419Sopenharmony_ciuse crate::daemon_lib::task_manager;
20cc290419Sopenharmony_ciuse crate::utils::hdc_log::*;
21cc290419Sopenharmony_ciuse crate::common::base::Base;
22cc290419Sopenharmony_ciuse crate::config::TaskMessage;
23cc290419Sopenharmony_ciuse crate::config::{HdcCommand, MessageLevel, SHELL_PROG};
24cc290419Sopenharmony_ciuse crate::transfer;
25cc290419Sopenharmony_ci
26cc290419Sopenharmony_ciuse std::collections::HashMap;
27cc290419Sopenharmony_ciuse std::io::{self, Error, ErrorKind};
28cc290419Sopenharmony_ciuse std::mem::MaybeUninit;
29cc290419Sopenharmony_ciuse std::os::fd::AsRawFd;
30cc290419Sopenharmony_ciuse std::process::Stdio;
31cc290419Sopenharmony_ciuse std::sync::{Arc, Once};
32cc290419Sopenharmony_ciuse std::env;
33cc290419Sopenharmony_ci
34cc290419Sopenharmony_ciuse ylong_runtime::process::pty_process::{Pty, PtyCommand};
35cc290419Sopenharmony_ciuse ylong_runtime::process::{Child, Command, ChildStdin, ChildStdout, ChildStderr};
36cc290419Sopenharmony_ciuse ylong_runtime::io::{AsyncReadExt, AsyncWriteExt, AsyncBufReader};
37cc290419Sopenharmony_ciuse ylong_runtime::sync::{mpsc, Mutex};
38cc290419Sopenharmony_ciuse ylong_runtime::sync::error::TryRecvError::Closed;
39cc290419Sopenharmony_ci
40cc290419Sopenharmony_ci
41cc290419Sopenharmony_ci// -----inner common functions-----
42cc290419Sopenharmony_ci#[derive(Debug)]
43cc290419Sopenharmony_cistruct ShellTaskID {
44cc290419Sopenharmony_ci    session_id: u32,
45cc290419Sopenharmony_ci    channel_id: u32,
46cc290419Sopenharmony_ci}
47cc290419Sopenharmony_ci
48cc290419Sopenharmony_cifn trim_quotation_for_cmd(cmd_input: String) -> String {
49cc290419Sopenharmony_ci    let mut cmd = cmd_input.trim().to_string();
50cc290419Sopenharmony_ci    if cmd.starts_with('"') && cmd.ends_with('"') {
51cc290419Sopenharmony_ci        cmd = match cmd.strip_prefix('"') {
52cc290419Sopenharmony_ci            Some(cmd_res) => cmd_res.to_string(),
53cc290419Sopenharmony_ci            None => cmd,
54cc290419Sopenharmony_ci        };
55cc290419Sopenharmony_ci        cmd = match cmd.strip_suffix('"') {
56cc290419Sopenharmony_ci            Some(cmd_res) => cmd_res.to_string(),
57cc290419Sopenharmony_ci            None => cmd,
58cc290419Sopenharmony_ci        };
59cc290419Sopenharmony_ci    }
60cc290419Sopenharmony_ci    cmd
61cc290419Sopenharmony_ci}
62cc290419Sopenharmony_ci
63cc290419Sopenharmony_ciasync fn shell_channel_close(channel_id: u32, session_id: u32){
64cc290419Sopenharmony_ci    let message = TaskMessage {
65cc290419Sopenharmony_ci        channel_id,
66cc290419Sopenharmony_ci        command: HdcCommand::KernelChannelClose,
67cc290419Sopenharmony_ci        payload: [1].to_vec(),
68cc290419Sopenharmony_ci    };
69cc290419Sopenharmony_ci    transfer::put(session_id, message).await;
70cc290419Sopenharmony_ci}
71cc290419Sopenharmony_ci
72cc290419Sopenharmony_cipub async fn stop_task(session_id: u32) {
73cc290419Sopenharmony_ci    PtyMap::stop_task(session_id).await;
74cc290419Sopenharmony_ci    ShellExecuteMap::stop_task(session_id).await;
75cc290419Sopenharmony_ci}
76cc290419Sopenharmony_ci
77cc290419Sopenharmony_cipub async fn dump_task() -> String {
78cc290419Sopenharmony_ci    PtyMap::dump_task().await
79cc290419Sopenharmony_ci}
80cc290419Sopenharmony_ci
81cc290419Sopenharmony_ci// -----interactive shell inplementation-----
82cc290419Sopenharmony_cipub struct PtyTask {
83cc290419Sopenharmony_ci    pub handle: ylong_runtime::task::JoinHandle<()>,
84cc290419Sopenharmony_ci    pub tx: mpsc::BoundedSender<Vec<u8>>,
85cc290419Sopenharmony_ci    pub session_id: u32,
86cc290419Sopenharmony_ci    pub channel_id: u32,
87cc290419Sopenharmony_ci    pub cmd: Option<String>,
88cc290419Sopenharmony_ci}
89cc290419Sopenharmony_ci
90cc290419Sopenharmony_cistruct PtyProcess {
91cc290419Sopenharmony_ci    pub pty: Pty,
92cc290419Sopenharmony_ci    pub child: Arc<Mutex<Child>>,
93cc290419Sopenharmony_ci}
94cc290419Sopenharmony_ci
95cc290419Sopenharmony_ciimpl PtyProcess {
96cc290419Sopenharmony_ci    fn new(pty: Pty, child: Arc<Mutex<Child>>) -> Self {
97cc290419Sopenharmony_ci        Self {
98cc290419Sopenharmony_ci            pty,
99cc290419Sopenharmony_ci            child,
100cc290419Sopenharmony_ci        }
101cc290419Sopenharmony_ci    }
102cc290419Sopenharmony_ci}
103cc290419Sopenharmony_ci
104cc290419Sopenharmony_ci// hdc shell "/system/bin/uitest start-daemon /data/app/el2/100/base/com.ohos.devicetest/cache/shmf &"
105cc290419Sopenharmony_ci// hdc shell "nohup test.sh &"
106cc290419Sopenharmony_ci// async cmd will ignor stdout and stderr, if you want the output, cmd format is:
107cc290419Sopenharmony_ci// hdc shell "cmd_xxx >/data/local/tmp/log 2>&1 &"
108cc290419Sopenharmony_ci// example:
109cc290419Sopenharmony_ci// hdc shell "nohup /data/local/tmp/test.sh >/data/local/tmp/log 2>&1 &"
110cc290419Sopenharmony_ci// hdc shell "/data/local/tmp/test.sh >/data/local/tmp/log 2>&1 &"
111cc290419Sopenharmony_cifn init_pty_process(cmd: Option<String>, _channel_id: u32) -> io::Result<PtyProcess> {
112cc290419Sopenharmony_ci    let pty = match Pty::new() {
113cc290419Sopenharmony_ci        Ok(pty) => pty,
114cc290419Sopenharmony_ci        Err(e) => {
115cc290419Sopenharmony_ci            let msg = format!("pty create error: {}", e);
116cc290419Sopenharmony_ci            crate::error!("{msg}");
117cc290419Sopenharmony_ci            return Err(io::Error::new(io::ErrorKind::Other, msg));
118cc290419Sopenharmony_ci        }
119cc290419Sopenharmony_ci    };
120cc290419Sopenharmony_ci
121cc290419Sopenharmony_ci    let pts = match pty.pts() {
122cc290419Sopenharmony_ci        Ok(pts) => pts,
123cc290419Sopenharmony_ci        Err(e) => {
124cc290419Sopenharmony_ci            let msg = format!("pty pts error: {}", e);
125cc290419Sopenharmony_ci            crate::error!("{msg}");
126cc290419Sopenharmony_ci            return Err(io::Error::new(io::ErrorKind::Other, msg));
127cc290419Sopenharmony_ci        }
128cc290419Sopenharmony_ci    };
129cc290419Sopenharmony_ci    let child = match cmd {
130cc290419Sopenharmony_ci        None => {
131cc290419Sopenharmony_ci            crate::debug!("input cmd is None. channel_id {_channel_id}");
132cc290419Sopenharmony_ci            let mut command = PtyCommand::new(SHELL_PROG);
133cc290419Sopenharmony_ci
134cc290419Sopenharmony_ci        unsafe {
135cc290419Sopenharmony_ci            command.pre_exec(|| {
136cc290419Sopenharmony_ci                Base::de_init_process();
137cc290419Sopenharmony_ci
138cc290419Sopenharmony_ci                let home_dir = match env::var("HOME") {
139cc290419Sopenharmony_ci                    Ok(dir) => dir,
140cc290419Sopenharmony_ci                    Err(_) => String::from("/")
141cc290419Sopenharmony_ci                };
142cc290419Sopenharmony_ci                let _ = std::env::set_current_dir(home_dir);
143cc290419Sopenharmony_ci
144cc290419Sopenharmony_ci                Ok(())
145cc290419Sopenharmony_ci            });
146cc290419Sopenharmony_ci        }
147cc290419Sopenharmony_ci
148cc290419Sopenharmony_ci            command.spawn(&pts)?
149cc290419Sopenharmony_ci        }
150cc290419Sopenharmony_ci        Some(mut cmd) => {
151cc290419Sopenharmony_ci            crate::debug!("input cmd [{}]", cmd);
152cc290419Sopenharmony_ci            cmd = trim_quotation_for_cmd(cmd);
153cc290419Sopenharmony_ci            let params = ["-c", cmd.as_str()].to_vec();
154cc290419Sopenharmony_ci            let mut proc = PtyCommand::new(SHELL_PROG);
155cc290419Sopenharmony_ci            let command = proc.args(params);
156cc290419Sopenharmony_ci            command.spawn(&pts)?
157cc290419Sopenharmony_ci        }
158cc290419Sopenharmony_ci    };
159cc290419Sopenharmony_ci    Ok(PtyProcess::new(
160cc290419Sopenharmony_ci        pty,
161cc290419Sopenharmony_ci        Arc::new(Mutex::new(child)),
162cc290419Sopenharmony_ci    ))
163cc290419Sopenharmony_ci}
164cc290419Sopenharmony_ci
165cc290419Sopenharmony_ciasync fn subprocess_task(
166cc290419Sopenharmony_ci    cmd: Option<String>,
167cc290419Sopenharmony_ci    session_id: u32,
168cc290419Sopenharmony_ci    channel_id: u32,
169cc290419Sopenharmony_ci    ret_command: HdcCommand,
170cc290419Sopenharmony_ci    mut rx: mpsc::BoundedReceiver<Vec<u8>>,
171cc290419Sopenharmony_ci) {
172cc290419Sopenharmony_ci    let mut pty_process = match init_pty_process(cmd.clone(), channel_id) {
173cc290419Sopenharmony_ci        Err(e) => {
174cc290419Sopenharmony_ci            let msg = format!("execute cmd [{cmd:?}] fail: {e:?}");
175cc290419Sopenharmony_ci            crate::error!("{}", msg);
176cc290419Sopenharmony_ci            crate::common::hdctransfer::echo_client(
177cc290419Sopenharmony_ci                session_id,
178cc290419Sopenharmony_ci                channel_id,
179cc290419Sopenharmony_ci                &msg,
180cc290419Sopenharmony_ci                MessageLevel::Fail,
181cc290419Sopenharmony_ci            )
182cc290419Sopenharmony_ci            .await;
183cc290419Sopenharmony_ci            shell_channel_close(channel_id, session_id).await;
184cc290419Sopenharmony_ci            return;
185cc290419Sopenharmony_ci        }
186cc290419Sopenharmony_ci        Ok(pty) => pty,
187cc290419Sopenharmony_ci    };
188cc290419Sopenharmony_ci    PtyChildProcessMap::put(session_id, channel_id, pty_process.child.clone()).await;
189cc290419Sopenharmony_ci    let mut buf = [0_u8; 30720];
190cc290419Sopenharmony_ci    loop {
191cc290419Sopenharmony_ci        ylong_runtime::select! {
192cc290419Sopenharmony_ci            read_res = pty_process.pty.read(&mut buf) => {
193cc290419Sopenharmony_ci                match read_res {
194cc290419Sopenharmony_ci                    Ok(bytes) => {
195cc290419Sopenharmony_ci                        let message = TaskMessage {
196cc290419Sopenharmony_ci                            channel_id,
197cc290419Sopenharmony_ci                            command: ret_command,
198cc290419Sopenharmony_ci                            payload: buf[..bytes].to_vec(),
199cc290419Sopenharmony_ci                        };
200cc290419Sopenharmony_ci                        transfer::put(session_id, message).await;
201cc290419Sopenharmony_ci                    }
202cc290419Sopenharmony_ci                    Err(e) => {
203cc290419Sopenharmony_ci                        crate::warn!("pty read failed: {e:?}");
204cc290419Sopenharmony_ci                        break;
205cc290419Sopenharmony_ci                    }
206cc290419Sopenharmony_ci                }
207cc290419Sopenharmony_ci            },
208cc290419Sopenharmony_ci            recv_res = rx.recv() => {
209cc290419Sopenharmony_ci                match recv_res {
210cc290419Sopenharmony_ci                    Ok(val) => {
211cc290419Sopenharmony_ci                        if val[..].contains(&0x4_u8) {
212cc290419Sopenharmony_ci                            // ctrl-D: end pty
213cc290419Sopenharmony_ci                            crate::info!("ctrl-D: end pty");
214cc290419Sopenharmony_ci                            break;
215cc290419Sopenharmony_ci                        } else if val[..].contains(&0x3_u8) {
216cc290419Sopenharmony_ci                            // ctrl-C: end process
217cc290419Sopenharmony_ci                            crate::info!("ctrl-C: end process");
218cc290419Sopenharmony_ci                            unsafe {
219cc290419Sopenharmony_ci                                let tpgid = libc::tcgetpgrp(pty_process.pty.as_raw_fd());
220cc290419Sopenharmony_ci                                if tpgid > 1 {
221cc290419Sopenharmony_ci                                    libc::kill(tpgid,libc::SIGINT);
222cc290419Sopenharmony_ci                                }
223cc290419Sopenharmony_ci                            }
224cc290419Sopenharmony_ci                            continue;
225cc290419Sopenharmony_ci                        } else if val[..].contains(&0x11_u8) {
226cc290419Sopenharmony_ci                            // ctrl-Q: dump process
227cc290419Sopenharmony_ci                            crate::info!("ctrl-Q: dump process");
228cc290419Sopenharmony_ci                            let dump_message = task_manager::dump_running_task_info().await;
229cc290419Sopenharmony_ci                            crate::debug!("dump_message: {}", dump_message);
230cc290419Sopenharmony_ci                            #[cfg(feature = "hdc_debug")]
231cc290419Sopenharmony_ci                            let message = TaskMessage {
232cc290419Sopenharmony_ci                                channel_id,
233cc290419Sopenharmony_ci                                command: ret_command,
234cc290419Sopenharmony_ci                                payload: dump_message.as_bytes().to_vec(),
235cc290419Sopenharmony_ci                            };
236cc290419Sopenharmony_ci                            #[cfg(feature = "hdc_debug")]
237cc290419Sopenharmony_ci                            transfer::put(session_id, message).await;
238cc290419Sopenharmony_ci                        }
239cc290419Sopenharmony_ci                        if let Err(e) = pty_process.pty.write_all(&val).await {
240cc290419Sopenharmony_ci                            crate::warn!(
241cc290419Sopenharmony_ci                                "session_id: {} channel_id: {}, pty write failed: {e:?}",
242cc290419Sopenharmony_ci                                session_id, channel_id
243cc290419Sopenharmony_ci                            );
244cc290419Sopenharmony_ci                            break;
245cc290419Sopenharmony_ci                        }
246cc290419Sopenharmony_ci                    }
247cc290419Sopenharmony_ci                    Err(e) => {
248cc290419Sopenharmony_ci                        crate::debug!("rx recv failed: {e:?}");
249cc290419Sopenharmony_ci                    }
250cc290419Sopenharmony_ci                }
251cc290419Sopenharmony_ci            }
252cc290419Sopenharmony_ci        }
253cc290419Sopenharmony_ci
254cc290419Sopenharmony_ci        {
255cc290419Sopenharmony_ci            let mut child_lock = pty_process.child.lock().await;
256cc290419Sopenharmony_ci            let status = child_lock.try_wait();
257cc290419Sopenharmony_ci            match status {
258cc290419Sopenharmony_ci                Ok(Some(exit_status)) => {
259cc290419Sopenharmony_ci                    crate::debug!("interactive shell finish a process {:?}", exit_status);
260cc290419Sopenharmony_ci                }
261cc290419Sopenharmony_ci                Ok(None) => {}
262cc290419Sopenharmony_ci                Err(e) => {
263cc290419Sopenharmony_ci                    crate::error!("interactive shell wait failed: {e:?}");
264cc290419Sopenharmony_ci                    break;
265cc290419Sopenharmony_ci                }
266cc290419Sopenharmony_ci            }
267cc290419Sopenharmony_ci        }
268cc290419Sopenharmony_ci    }
269cc290419Sopenharmony_ci
270cc290419Sopenharmony_ci    let mut child_lock = pty_process.child.lock().await;
271cc290419Sopenharmony_ci
272cc290419Sopenharmony_ci    let kill_result = child_lock.kill().await;
273cc290419Sopenharmony_ci    crate::debug!("subprocess_task kill child(session_id {session_id}, channel_id {channel_id}), result:{:?}", kill_result);
274cc290419Sopenharmony_ci    match child_lock.wait().await {
275cc290419Sopenharmony_ci        Ok(exit_status) => {
276cc290419Sopenharmony_ci            PtyMap::del(session_id, channel_id).await;
277cc290419Sopenharmony_ci            crate::debug!(
278cc290419Sopenharmony_ci                "subprocess_task waiting child exit success, status:{:?}.",
279cc290419Sopenharmony_ci                exit_status
280cc290419Sopenharmony_ci            );
281cc290419Sopenharmony_ci        }
282cc290419Sopenharmony_ci        Err(e) => {
283cc290419Sopenharmony_ci            let kill_result = child_lock.kill().await;
284cc290419Sopenharmony_ci            crate::debug!(
285cc290419Sopenharmony_ci                "subprocess_task child exit status {:?}, kill child, result:{:?}",
286cc290419Sopenharmony_ci                e,
287cc290419Sopenharmony_ci                kill_result
288cc290419Sopenharmony_ci            );
289cc290419Sopenharmony_ci        }
290cc290419Sopenharmony_ci    }
291cc290419Sopenharmony_ci
292cc290419Sopenharmony_ci    match child_lock.wait().await {
293cc290419Sopenharmony_ci        Ok(exit_status) => {
294cc290419Sopenharmony_ci            PtyMap::del(session_id, channel_id).await;
295cc290419Sopenharmony_ci            crate::debug!(
296cc290419Sopenharmony_ci                "subprocess_task waiting child exit success, status:{:?}.",
297cc290419Sopenharmony_ci                exit_status
298cc290419Sopenharmony_ci            );
299cc290419Sopenharmony_ci        }
300cc290419Sopenharmony_ci        Err(e) => {
301cc290419Sopenharmony_ci            crate::debug!("subprocess_task waiting child exit fail, error:{:?}.", e);
302cc290419Sopenharmony_ci        }
303cc290419Sopenharmony_ci    }
304cc290419Sopenharmony_ci
305cc290419Sopenharmony_ci    let message = TaskMessage {
306cc290419Sopenharmony_ci        channel_id,
307cc290419Sopenharmony_ci        command: HdcCommand::KernelChannelClose,
308cc290419Sopenharmony_ci        payload: vec![1],
309cc290419Sopenharmony_ci    };
310cc290419Sopenharmony_ci    transfer::put(session_id, message).await;
311cc290419Sopenharmony_ci}
312cc290419Sopenharmony_ci
313cc290419Sopenharmony_ciimpl PtyTask {
314cc290419Sopenharmony_ci    pub fn new(
315cc290419Sopenharmony_ci        session_id: u32,
316cc290419Sopenharmony_ci        channel_id: u32,
317cc290419Sopenharmony_ci        option_cmd: Option<String>,
318cc290419Sopenharmony_ci        ret_command: HdcCommand,
319cc290419Sopenharmony_ci    ) -> Self {
320cc290419Sopenharmony_ci        let (tx, rx) = ylong_runtime::sync::mpsc::bounded_channel::<Vec<u8>>(16);
321cc290419Sopenharmony_ci        let cmd = option_cmd.clone();
322cc290419Sopenharmony_ci        crate::debug!("PtyTask new session_id {session_id}, channel_id {channel_id}");
323cc290419Sopenharmony_ci        let handle = ylong_runtime::spawn(subprocess_task(
324cc290419Sopenharmony_ci            option_cmd,
325cc290419Sopenharmony_ci            session_id,
326cc290419Sopenharmony_ci            channel_id,
327cc290419Sopenharmony_ci            ret_command,
328cc290419Sopenharmony_ci            rx,
329cc290419Sopenharmony_ci        ));
330cc290419Sopenharmony_ci        Self {
331cc290419Sopenharmony_ci            handle,
332cc290419Sopenharmony_ci            tx,
333cc290419Sopenharmony_ci            session_id,
334cc290419Sopenharmony_ci            channel_id,
335cc290419Sopenharmony_ci            cmd,
336cc290419Sopenharmony_ci        }
337cc290419Sopenharmony_ci    }
338cc290419Sopenharmony_ci}
339cc290419Sopenharmony_ci
340cc290419Sopenharmony_ciimpl Drop for PtyTask {
341cc290419Sopenharmony_ci    fn drop(&mut self) {
342cc290419Sopenharmony_ci        crate::info!(
343cc290419Sopenharmony_ci            "PtyTask Drop session_id {}, channel_id {}",
344cc290419Sopenharmony_ci            self.session_id,
345cc290419Sopenharmony_ci            self.channel_id
346cc290419Sopenharmony_ci        );
347cc290419Sopenharmony_ci    }
348cc290419Sopenharmony_ci}
349cc290419Sopenharmony_ci
350cc290419Sopenharmony_citype Child_ = Arc<Mutex<Child>>;
351cc290419Sopenharmony_citype PtyChildProcessMap_ = Arc<Mutex<HashMap<(u32, u32), Child_>>>;
352cc290419Sopenharmony_cipub struct PtyChildProcessMap {}
353cc290419Sopenharmony_ciimpl PtyChildProcessMap {
354cc290419Sopenharmony_ci    fn get_instance() -> PtyChildProcessMap_ {
355cc290419Sopenharmony_ci        static mut PTY_CHILD_MAP: Option<PtyChildProcessMap_> = None;
356cc290419Sopenharmony_ci        unsafe {
357cc290419Sopenharmony_ci            PTY_CHILD_MAP
358cc290419Sopenharmony_ci                .get_or_insert_with(|| Arc::new(Mutex::new(HashMap::new())))
359cc290419Sopenharmony_ci                .clone()
360cc290419Sopenharmony_ci        }
361cc290419Sopenharmony_ci    }
362cc290419Sopenharmony_ci
363cc290419Sopenharmony_ci    pub async fn get(session_id: u32, channel_id: u32) -> Option<Child_> {
364cc290419Sopenharmony_ci        let pty_child_map = Self::get_instance();
365cc290419Sopenharmony_ci        let map = pty_child_map.lock().await;
366cc290419Sopenharmony_ci        if let Some(pty_child) = map.get(&(session_id, channel_id)) {
367cc290419Sopenharmony_ci            return Some(pty_child.clone());
368cc290419Sopenharmony_ci        }
369cc290419Sopenharmony_ci        None
370cc290419Sopenharmony_ci    }
371cc290419Sopenharmony_ci
372cc290419Sopenharmony_ci    #[allow(unused)]
373cc290419Sopenharmony_ci    pub async fn put(session_id: u32, channel_id: u32, pty_child: Child_) {
374cc290419Sopenharmony_ci        let pty_child_map = Self::get_instance();
375cc290419Sopenharmony_ci        let mut map = pty_child_map.lock().await;
376cc290419Sopenharmony_ci        map.insert((session_id, channel_id), pty_child);
377cc290419Sopenharmony_ci    }
378cc290419Sopenharmony_ci
379cc290419Sopenharmony_ci    pub async fn del(session_id: u32, channel_id: u32) {
380cc290419Sopenharmony_ci        let pty_child_map = Self::get_instance();
381cc290419Sopenharmony_ci        let mut map = pty_child_map.lock().await;
382cc290419Sopenharmony_ci        map.remove(&(session_id, channel_id));
383cc290419Sopenharmony_ci    }
384cc290419Sopenharmony_ci}
385cc290419Sopenharmony_ci
386cc290419Sopenharmony_citype PtyMap_ = Arc<Mutex<HashMap<(u32, u32), Arc<PtyTask>>>>;
387cc290419Sopenharmony_cipub struct PtyMap {}
388cc290419Sopenharmony_ciimpl PtyMap {
389cc290419Sopenharmony_ci    fn get_instance() -> PtyMap_ {
390cc290419Sopenharmony_ci        static mut PTY_MAP: Option<PtyMap_> = None;
391cc290419Sopenharmony_ci        unsafe {
392cc290419Sopenharmony_ci            PTY_MAP
393cc290419Sopenharmony_ci                .get_or_insert_with(|| Arc::new(Mutex::new(HashMap::new())))
394cc290419Sopenharmony_ci                .clone()
395cc290419Sopenharmony_ci        }
396cc290419Sopenharmony_ci    }
397cc290419Sopenharmony_ci
398cc290419Sopenharmony_ci    pub async fn get(session_id: u32, channel_id: u32) -> Option<Arc<PtyTask>> {
399cc290419Sopenharmony_ci        let pty_map = Self::get_instance();
400cc290419Sopenharmony_ci        let map = pty_map.lock().await;
401cc290419Sopenharmony_ci        if let Some(pty_task) = map.get(&(session_id, channel_id)) {
402cc290419Sopenharmony_ci            return Some(pty_task.clone());
403cc290419Sopenharmony_ci        }
404cc290419Sopenharmony_ci        None
405cc290419Sopenharmony_ci    }
406cc290419Sopenharmony_ci
407cc290419Sopenharmony_ci    pub async fn put(session_id: u32, channel_id: u32, pty_task: PtyTask) {
408cc290419Sopenharmony_ci        let pty_map = Self::get_instance();
409cc290419Sopenharmony_ci        let mut map = pty_map.lock().await;
410cc290419Sopenharmony_ci        let arc_pty_task = Arc::new(pty_task);
411cc290419Sopenharmony_ci        map.insert((session_id, channel_id), arc_pty_task);
412cc290419Sopenharmony_ci    }
413cc290419Sopenharmony_ci
414cc290419Sopenharmony_ci    pub async fn del(session_id: u32, channel_id: u32) {
415cc290419Sopenharmony_ci        let pty_map = Self::get_instance();
416cc290419Sopenharmony_ci        let mut map = pty_map.lock().await;
417cc290419Sopenharmony_ci        map.remove(&(session_id, channel_id));
418cc290419Sopenharmony_ci        PtyChildProcessMap::del(session_id, channel_id).await;
419cc290419Sopenharmony_ci    }
420cc290419Sopenharmony_ci
421cc290419Sopenharmony_ci    pub async fn stop_task(session_id: u32) {
422cc290419Sopenharmony_ci        let pty_map = Self::get_instance();
423cc290419Sopenharmony_ci        {
424cc290419Sopenharmony_ci            let map = pty_map.lock().await;
425cc290419Sopenharmony_ci            crate::info!("hdc shell stop_task, session_id:{}, task_size: {}", session_id, map.len());
426cc290419Sopenharmony_ci            for _iter in map.iter() {
427cc290419Sopenharmony_ci                if _iter.0 .0 != session_id {
428cc290419Sopenharmony_ci                    continue;
429cc290419Sopenharmony_ci                }
430cc290419Sopenharmony_ci                if let Some(pty_child) = PtyChildProcessMap::get(session_id, _iter.0 .1).await {
431cc290419Sopenharmony_ci                    let mut child = pty_child.lock().await;
432cc290419Sopenharmony_ci                    let kill_result = child.kill().await;
433cc290419Sopenharmony_ci                    crate::debug!(
434cc290419Sopenharmony_ci                        "do map clear kill child, result:{:?}, session_id {}, channel_id {}",
435cc290419Sopenharmony_ci                        kill_result,
436cc290419Sopenharmony_ci                        session_id,
437cc290419Sopenharmony_ci                        _iter.0 .1
438cc290419Sopenharmony_ci                    );
439cc290419Sopenharmony_ci                    match child.wait().await {
440cc290419Sopenharmony_ci                        Ok(exit_status) => {
441cc290419Sopenharmony_ci                            crate::debug!(
442cc290419Sopenharmony_ci                                "waiting child exit success, status:{:?}, session_id {}, channel_id {}",
443cc290419Sopenharmony_ci                                exit_status,
444cc290419Sopenharmony_ci                                session_id,
445cc290419Sopenharmony_ci                                _iter.0.1
446cc290419Sopenharmony_ci                            );
447cc290419Sopenharmony_ci                        }
448cc290419Sopenharmony_ci                        Err(e) => {
449cc290419Sopenharmony_ci                            crate::error!(
450cc290419Sopenharmony_ci                                "waiting child exit fail, error:{:?}, session_id {}, channel_id {}",
451cc290419Sopenharmony_ci                                e,
452cc290419Sopenharmony_ci                                session_id,
453cc290419Sopenharmony_ci                                _iter.0 .1
454cc290419Sopenharmony_ci                            );
455cc290419Sopenharmony_ci                        }
456cc290419Sopenharmony_ci                    }
457cc290419Sopenharmony_ci                    PtyChildProcessMap::del(session_id, _iter.0 .1).await;
458cc290419Sopenharmony_ci                }
459cc290419Sopenharmony_ci                crate::debug!(
460cc290419Sopenharmony_ci                    "Clear tty task, session_id: {}, channel_id:{}",
461cc290419Sopenharmony_ci                    _iter.0 .0,
462cc290419Sopenharmony_ci                    session_id
463cc290419Sopenharmony_ci                );
464cc290419Sopenharmony_ci            }
465cc290419Sopenharmony_ci        }
466cc290419Sopenharmony_ci    }
467cc290419Sopenharmony_ci
468cc290419Sopenharmony_ci    pub async fn dump_task() -> String {
469cc290419Sopenharmony_ci        let arc = Self::get_instance();
470cc290419Sopenharmony_ci        let map = arc.lock().await;
471cc290419Sopenharmony_ci        let mut result = String::new();
472cc290419Sopenharmony_ci        for _iter in map.iter() {
473cc290419Sopenharmony_ci            let command = match &_iter.1.cmd {
474cc290419Sopenharmony_ci                Some(b) => b,
475cc290419Sopenharmony_ci                _ => "",
476cc290419Sopenharmony_ci            };
477cc290419Sopenharmony_ci            result.push_str(&format!(
478cc290419Sopenharmony_ci                "session_id:{},\tchannel_id:{},\tcommand:{}\n",
479cc290419Sopenharmony_ci                _iter.1.session_id, _iter.1.channel_id, command
480cc290419Sopenharmony_ci            ));
481cc290419Sopenharmony_ci        }
482cc290419Sopenharmony_ci        result
483cc290419Sopenharmony_ci    }
484cc290419Sopenharmony_ci}
485cc290419Sopenharmony_ci
486cc290419Sopenharmony_ci// -----noninteractive shell implementation-----
487cc290419Sopenharmony_ci
488cc290419Sopenharmony_citype ShellExecuteMap_ = Mutex<HashMap<(u32, u32), Arc<ShellExecuteTask>>>;
489cc290419Sopenharmony_cipub struct ShellExecuteMap {}
490cc290419Sopenharmony_ciimpl ShellExecuteMap {
491cc290419Sopenharmony_ci    fn get_instance() -> &'static ShellExecuteMap_ {
492cc290419Sopenharmony_ci        static mut SHELLEXECUTE_MAP: MaybeUninit<ShellExecuteMap_> = MaybeUninit::uninit();
493cc290419Sopenharmony_ci        static ONCE: Once = Once::new();
494cc290419Sopenharmony_ci
495cc290419Sopenharmony_ci        unsafe {
496cc290419Sopenharmony_ci            ONCE.call_once(|| {
497cc290419Sopenharmony_ci                    SHELLEXECUTE_MAP = MaybeUninit::new(Mutex::new(HashMap::new()));
498cc290419Sopenharmony_ci                }
499cc290419Sopenharmony_ci            );
500cc290419Sopenharmony_ci            &*SHELLEXECUTE_MAP.as_ptr()
501cc290419Sopenharmony_ci        }
502cc290419Sopenharmony_ci    }
503cc290419Sopenharmony_ci
504cc290419Sopenharmony_ci    pub async fn put(session_id: u32, channel_id: u32, shell_execute_task: ShellExecuteTask) {
505cc290419Sopenharmony_ci        let shell_execute_map = Self::get_instance();
506cc290419Sopenharmony_ci        let mut map = shell_execute_map.lock().await;
507cc290419Sopenharmony_ci        let arc_shell_execute_task = Arc::new(shell_execute_task);
508cc290419Sopenharmony_ci        map.insert((session_id, channel_id), arc_shell_execute_task);
509cc290419Sopenharmony_ci    }
510cc290419Sopenharmony_ci
511cc290419Sopenharmony_ci    pub async fn del(session_id: u32, channel_id: u32) {
512cc290419Sopenharmony_ci        let shell_execute_map = Self::get_instance();
513cc290419Sopenharmony_ci        let mut map = shell_execute_map.lock().await;
514cc290419Sopenharmony_ci        map.remove(&(session_id, channel_id));
515cc290419Sopenharmony_ci    }
516cc290419Sopenharmony_ci
517cc290419Sopenharmony_ci    pub async fn stop_task(session_id: u32) {
518cc290419Sopenharmony_ci        let shell_execute_map = Self::get_instance();
519cc290419Sopenharmony_ci        {
520cc290419Sopenharmony_ci            let mut map = shell_execute_map.lock().await;
521cc290419Sopenharmony_ci            let mut channel_vec = vec![];
522cc290419Sopenharmony_ci            for iter in map.iter() {
523cc290419Sopenharmony_ci                if iter.0 .0 != session_id {
524cc290419Sopenharmony_ci                    continue;
525cc290419Sopenharmony_ci                }
526cc290419Sopenharmony_ci                iter.1.handle.cancel();
527cc290419Sopenharmony_ci                channel_vec.push(iter.0 .1);
528cc290419Sopenharmony_ci                crate::debug!(
529cc290419Sopenharmony_ci                    "Clear shell_execute_map task, session_id: {}, channel_id:{}, task_size: {}",
530cc290419Sopenharmony_ci                    session_id,
531cc290419Sopenharmony_ci                    iter.0 .1,
532cc290419Sopenharmony_ci                    map.len(),
533cc290419Sopenharmony_ci                );
534cc290419Sopenharmony_ci            }
535cc290419Sopenharmony_ci            for channel_id in channel_vec{
536cc290419Sopenharmony_ci                map.remove(&(session_id, channel_id));
537cc290419Sopenharmony_ci            }
538cc290419Sopenharmony_ci        }
539cc290419Sopenharmony_ci    }
540cc290419Sopenharmony_ci
541cc290419Sopenharmony_ci}
542cc290419Sopenharmony_ci
543cc290419Sopenharmony_cipub struct ShellExecuteTask {
544cc290419Sopenharmony_ci    pub handle: ylong_runtime::task::JoinHandle<()>,
545cc290419Sopenharmony_ci    pub tx: mpsc::BoundedSender<Vec<u8>>,
546cc290419Sopenharmony_ci    pub session_id: u32,
547cc290419Sopenharmony_ci    pub channel_id: u32,
548cc290419Sopenharmony_ci    pub cmd: String,
549cc290419Sopenharmony_ci}
550cc290419Sopenharmony_ci
551cc290419Sopenharmony_ci
552cc290419Sopenharmony_ciasync fn watch_pipe_states(rx: &mut mpsc::BoundedReceiver<Vec<u8>>, child_in: &mut ChildStdin) -> io::Result<()> {
553cc290419Sopenharmony_ci    match rx.try_recv() {
554cc290419Sopenharmony_ci        Err(e) => {
555cc290419Sopenharmony_ci            if e == Closed {
556cc290419Sopenharmony_ci                return Err(Error::new(ErrorKind::Other, "pipe closed"));
557cc290419Sopenharmony_ci            }
558cc290419Sopenharmony_ci            // 执行top指令时,存在短暂无返回值场景,此时返回值为Err(Empty),需要返回Empty
559cc290419Sopenharmony_ci            Ok(())
560cc290419Sopenharmony_ci        },
561cc290419Sopenharmony_ci        Ok(val) => {
562cc290419Sopenharmony_ci            crate::debug!("pipe recv {:?}", val);
563cc290419Sopenharmony_ci            let _ = child_in.write_all(&val).await;
564cc290419Sopenharmony_ci            Ok(())
565cc290419Sopenharmony_ci        }
566cc290419Sopenharmony_ci    }
567cc290419Sopenharmony_ci}
568cc290419Sopenharmony_ci
569cc290419Sopenharmony_ci
570cc290419Sopenharmony_ciasync fn read_buf_from_stdout_stderr(child_out_reader: &mut AsyncBufReader<ChildStdout>, child_err_reader: &mut AsyncBufReader<ChildStderr>, shell_task_id: &ShellTaskID,  ret_command: HdcCommand) {
571cc290419Sopenharmony_ci    let mut buffer = Vec::new();
572cc290419Sopenharmony_ci    if let Ok(n) = child_out_reader.read_to_end(&mut buffer).await {
573cc290419Sopenharmony_ci        crate::debug!("read {n} bytes child_out after child exit");
574cc290419Sopenharmony_ci        if n > 0 {
575cc290419Sopenharmony_ci            let message = TaskMessage {
576cc290419Sopenharmony_ci                channel_id: shell_task_id.channel_id,
577cc290419Sopenharmony_ci                command: ret_command,
578cc290419Sopenharmony_ci                payload: buffer,
579cc290419Sopenharmony_ci            };
580cc290419Sopenharmony_ci            transfer::put(shell_task_id.session_id, message).await;
581cc290419Sopenharmony_ci        }
582cc290419Sopenharmony_ci    }
583cc290419Sopenharmony_ci
584cc290419Sopenharmony_ci    let mut buffer = Vec::new();
585cc290419Sopenharmony_ci    if let Ok(n) = child_err_reader.read_to_end(&mut buffer).await {
586cc290419Sopenharmony_ci        crate::debug!("read {n} bytes child_err  child exit");
587cc290419Sopenharmony_ci        if n > 0 {
588cc290419Sopenharmony_ci            let message = TaskMessage {
589cc290419Sopenharmony_ci                channel_id: shell_task_id.channel_id,
590cc290419Sopenharmony_ci                command: ret_command,
591cc290419Sopenharmony_ci                payload: buffer,
592cc290419Sopenharmony_ci            };
593cc290419Sopenharmony_ci            transfer::put(shell_task_id.session_id, message).await;
594cc290419Sopenharmony_ci        }
595cc290419Sopenharmony_ci    }
596cc290419Sopenharmony_ci}
597cc290419Sopenharmony_ci
598cc290419Sopenharmony_ciasync fn task_for_shell_execute(
599cc290419Sopenharmony_ci    cmd_param: String,
600cc290419Sopenharmony_ci    shell_task_id: ShellTaskID,
601cc290419Sopenharmony_ci    ret_command: HdcCommand,
602cc290419Sopenharmony_ci    mut rx: mpsc::BoundedReceiver<Vec<u8>>,
603cc290419Sopenharmony_ci) {
604cc290419Sopenharmony_ci    crate::info!(
605cc290419Sopenharmony_ci        "Execute cmd:[{:?}], session_id: {}, channel_id: {}",
606cc290419Sopenharmony_ci        cmd_param,
607cc290419Sopenharmony_ci        shell_task_id.session_id,
608cc290419Sopenharmony_ci        shell_task_id.channel_id,
609cc290419Sopenharmony_ci    );
610cc290419Sopenharmony_ci    let cmd = trim_quotation_for_cmd(cmd_param);
611cc290419Sopenharmony_ci    let mut shell_cmd = Command::new(SHELL_PROG);
612cc290419Sopenharmony_ci    shell_cmd.args(["-c", &cmd])
613cc290419Sopenharmony_ci        .stdout(Stdio::piped())
614cc290419Sopenharmony_ci        .stdin(Stdio::piped())
615cc290419Sopenharmony_ci        .stderr(Stdio::piped())
616cc290419Sopenharmony_ci        .kill_on_drop(true);
617cc290419Sopenharmony_ci
618cc290419Sopenharmony_ci    unsafe {
619cc290419Sopenharmony_ci        shell_cmd.pre_exec(|| {
620cc290419Sopenharmony_ci            Base::de_init_process();
621cc290419Sopenharmony_ci            libc::setsid();
622cc290419Sopenharmony_ci            let pid = libc::getpid();
623cc290419Sopenharmony_ci            libc::setpgid(pid, pid);
624cc290419Sopenharmony_ci            Ok(())
625cc290419Sopenharmony_ci        });
626cc290419Sopenharmony_ci    }
627cc290419Sopenharmony_ci
628cc290419Sopenharmony_ci    if let Ok(mut child) = shell_cmd.spawn() {
629cc290419Sopenharmony_ci
630cc290419Sopenharmony_ci        let mut child_in = match child.take_stdin() {
631cc290419Sopenharmony_ci            Some(child_in_inner) => {
632cc290419Sopenharmony_ci                child_in_inner
633cc290419Sopenharmony_ci            },
634cc290419Sopenharmony_ci            None => {
635cc290419Sopenharmony_ci                crate::error!("take_stdin failed");
636cc290419Sopenharmony_ci                shell_channel_close(shell_task_id.channel_id, shell_task_id.session_id).await;
637cc290419Sopenharmony_ci                return;
638cc290419Sopenharmony_ci            },
639cc290419Sopenharmony_ci        };
640cc290419Sopenharmony_ci
641cc290419Sopenharmony_ci        let child_out = match child.take_stdout() {
642cc290419Sopenharmony_ci            Some(child_out_inner) => {
643cc290419Sopenharmony_ci                child_out_inner
644cc290419Sopenharmony_ci            },
645cc290419Sopenharmony_ci            None => {
646cc290419Sopenharmony_ci                crate::error!("take_stdin failed");
647cc290419Sopenharmony_ci                shell_channel_close(shell_task_id.channel_id, shell_task_id.session_id).await;
648cc290419Sopenharmony_ci                return;
649cc290419Sopenharmony_ci            },
650cc290419Sopenharmony_ci        };
651cc290419Sopenharmony_ci
652cc290419Sopenharmony_ci        let child_err = match child.take_stderr() {
653cc290419Sopenharmony_ci            Some(child_err_inner) => {
654cc290419Sopenharmony_ci                child_err_inner
655cc290419Sopenharmony_ci            },
656cc290419Sopenharmony_ci            None => {
657cc290419Sopenharmony_ci                crate::error!("take_stdin failed");
658cc290419Sopenharmony_ci                shell_channel_close(shell_task_id.channel_id, shell_task_id.session_id).await;
659cc290419Sopenharmony_ci                return;
660cc290419Sopenharmony_ci            },
661cc290419Sopenharmony_ci        };
662cc290419Sopenharmony_ci
663cc290419Sopenharmony_ci        let mut child_out_reader = ylong_runtime::io::AsyncBufReader::new(child_out);
664cc290419Sopenharmony_ci        let mut child_err_reader = ylong_runtime::io::AsyncBufReader::new(child_err);
665cc290419Sopenharmony_ci        let mut buf_out = [0u8; 30720];
666cc290419Sopenharmony_ci        let mut buf_err = [0u8; 30720];
667cc290419Sopenharmony_ci
668cc290419Sopenharmony_ci        loop {
669cc290419Sopenharmony_ci            ylong_runtime::select! {
670cc290419Sopenharmony_ci                read_res = child_out_reader.read(&mut buf_out) => {
671cc290419Sopenharmony_ci                    match read_res {
672cc290419Sopenharmony_ci                        Ok(bytes) => {
673cc290419Sopenharmony_ci                            let message = TaskMessage {
674cc290419Sopenharmony_ci                                channel_id: shell_task_id.channel_id,
675cc290419Sopenharmony_ci                                command: ret_command,
676cc290419Sopenharmony_ci                                payload: buf_out[..bytes].to_vec(),
677cc290419Sopenharmony_ci                            };
678cc290419Sopenharmony_ci                            transfer::put(shell_task_id.session_id, message).await;
679cc290419Sopenharmony_ci                        }
680cc290419Sopenharmony_ci                        Err(e) => {
681cc290419Sopenharmony_ci                            crate::warn!("pty read failed: {e:?}");
682cc290419Sopenharmony_ci                            break;
683cc290419Sopenharmony_ci                        }
684cc290419Sopenharmony_ci                    }
685cc290419Sopenharmony_ci                },
686cc290419Sopenharmony_ci
687cc290419Sopenharmony_ci                read_res = child_err_reader.read(&mut buf_err) => {
688cc290419Sopenharmony_ci                    match read_res {
689cc290419Sopenharmony_ci                        Ok(bytes) => {
690cc290419Sopenharmony_ci                            let message = TaskMessage {
691cc290419Sopenharmony_ci                                channel_id: shell_task_id.channel_id,
692cc290419Sopenharmony_ci                                command: ret_command,
693cc290419Sopenharmony_ci                                payload: buf_err[..bytes].to_vec(),
694cc290419Sopenharmony_ci                            };
695cc290419Sopenharmony_ci                            transfer::put(shell_task_id.session_id, message).await;
696cc290419Sopenharmony_ci                        }
697cc290419Sopenharmony_ci                        Err(e) => {
698cc290419Sopenharmony_ci                            crate::warn!("pty read failed: {e:?}");
699cc290419Sopenharmony_ci                            break;
700cc290419Sopenharmony_ci                        }
701cc290419Sopenharmony_ci                    }
702cc290419Sopenharmony_ci                }
703cc290419Sopenharmony_ci            }
704cc290419Sopenharmony_ci
705cc290419Sopenharmony_ci            if (watch_pipe_states(&mut rx, &mut child_in).await).is_err() {
706cc290419Sopenharmony_ci                crate::warn!("pipe closed shell_task_id:{:?}", shell_task_id);
707cc290419Sopenharmony_ci                break;
708cc290419Sopenharmony_ci            }
709cc290419Sopenharmony_ci
710cc290419Sopenharmony_ci            match child.try_wait() {
711cc290419Sopenharmony_ci                Ok(Some(status)) => {
712cc290419Sopenharmony_ci                    crate::debug!("child exited with:{status} shell_task_id:{:?}", shell_task_id);
713cc290419Sopenharmony_ci                    read_buf_from_stdout_stderr(&mut child_out_reader, &mut child_err_reader, &shell_task_id, ret_command).await;
714cc290419Sopenharmony_ci                    break;
715cc290419Sopenharmony_ci                },
716cc290419Sopenharmony_ci                Ok(None) => {},
717cc290419Sopenharmony_ci                Err(e) => {
718cc290419Sopenharmony_ci                    crate::warn!("child exited with: {:?} shell_task_id:{:?}", e, shell_task_id);
719cc290419Sopenharmony_ci                    break;
720cc290419Sopenharmony_ci                }
721cc290419Sopenharmony_ci            }
722cc290419Sopenharmony_ci        }
723cc290419Sopenharmony_ci
724cc290419Sopenharmony_ci        let _ = child.kill().await;
725cc290419Sopenharmony_ci        crate::debug!("child kill shell_task_id:{:?}", shell_task_id);
726cc290419Sopenharmony_ci        let _ = child.wait().await;
727cc290419Sopenharmony_ci        crate::debug!("shell execute finish shell_task_id:{:?}", shell_task_id);
728cc290419Sopenharmony_ci    } else {
729cc290419Sopenharmony_ci        crate::debug!("shell spawn failed shell_task_id:{:?}", shell_task_id);
730cc290419Sopenharmony_ci    }
731cc290419Sopenharmony_ci
732cc290419Sopenharmony_ci    ShellExecuteMap::del(shell_task_id.session_id, shell_task_id.channel_id).await;
733cc290419Sopenharmony_ci    shell_channel_close(shell_task_id.channel_id, shell_task_id.session_id).await;
734cc290419Sopenharmony_ci}
735cc290419Sopenharmony_ci
736cc290419Sopenharmony_ci
737cc290419Sopenharmony_ci
738cc290419Sopenharmony_ciimpl ShellExecuteTask {
739cc290419Sopenharmony_ci    pub fn new(
740cc290419Sopenharmony_ci        session_id: u32,
741cc290419Sopenharmony_ci        channel_id: u32,
742cc290419Sopenharmony_ci        cmd_param: String,
743cc290419Sopenharmony_ci        ret_command: HdcCommand,
744cc290419Sopenharmony_ci    ) -> Self {
745cc290419Sopenharmony_ci        let (tx, rx) = ylong_runtime::sync::mpsc::bounded_channel::<Vec<u8>>(16);
746cc290419Sopenharmony_ci        let cmd = cmd_param.clone();
747cc290419Sopenharmony_ci        crate::debug!("ShellExecuteTask new session_id {session_id}, channel_id {channel_id}");
748cc290419Sopenharmony_ci        let shell_task_id = ShellTaskID {session_id, channel_id};
749cc290419Sopenharmony_ci        let handle = ylong_runtime::spawn(task_for_shell_execute(
750cc290419Sopenharmony_ci            cmd_param,
751cc290419Sopenharmony_ci            shell_task_id,
752cc290419Sopenharmony_ci            ret_command,
753cc290419Sopenharmony_ci            rx,
754cc290419Sopenharmony_ci        ));
755cc290419Sopenharmony_ci        Self {
756cc290419Sopenharmony_ci            handle,
757cc290419Sopenharmony_ci            tx,
758cc290419Sopenharmony_ci            session_id,
759cc290419Sopenharmony_ci            channel_id,
760cc290419Sopenharmony_ci            cmd,
761cc290419Sopenharmony_ci        }
762cc290419Sopenharmony_ci    }
763cc290419Sopenharmony_ci}
764