// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    anyhow::{format_err, Context as _, Error},
    cstr::cstr,
    fidl::endpoints::Proxy,
    fidl_fuchsia_hardware_pty::{DeviceMarker, DeviceProxy, WindowSize},
    fuchsia_async as fasync,
    fuchsia_component::client::connect_to_service,
    fuchsia_trace as ftrace,
    fuchsia_zircon::{self as zx, HandleBased, ProcessInfo, ProcessInfoFlags},
    std::{ffi::CStr, fs::File, os::unix::io::AsRawFd},
};

/// An object used for interacting with the shell
pub struct Pty {
    // The server side file descriptor. This file is safe to clone.
    server_pty: File,

    // The running shell process. This process will be closed when the
    // Pty goes out of scope so there is no need to explicitly close it.
    shell_process: Option<zx::Process>,
}

impl Pty {
    /// Creates a new instance of the Pty which must later be spawned.
    pub fn new() -> Result<Self, Error> {
        let server_pty = Pty::open_server_pty()?;
        let shell_process = None;
        Ok(Pty { server_pty, shell_process })
    }

    /// Spawns the Pty.
    ///
    /// If no command is provided the default /boot/bin/sh will be used.
    ///
    /// After calling this method the user must call resize to give the process a
    /// valid window size before it will respond.
    ///
    /// The launched process will close when the Pty is dropped so you do not need to
    /// explicitly close it.
    pub async fn spawn(&mut self, command: Option<&CStr>) -> Result<(), Error> {
        if self.shell_process.is_some() {
            return Ok(());
        }

        ftrace::duration!("terminal", "Pty:spawn");

        self.shell_process = Some(
            Pty::launch_shell(&self.server_pty, command.unwrap_or(&cstr!("/boot/bin/sh")))
                .await
                .context("launch shell process")?,
        );
        Ok(())
    }

    /// Returns the shell process info, if available.
    pub fn shell_process_info(&self) -> Option<ProcessInfo> {
        self.shell_process.as_ref().and_then(|p| match p.info() {
            Ok(info) => Some(info),
            Err(status) => {
                eprintln!("Failed to check shell process info, got status {:?}.", status);
                None
            }
        })
    }

    /// Checks that the shell process has been started and has not exited.
    pub fn is_shell_process_running(&self) -> bool {
        self.shell_process_info()
            .map(|info| {
                let flags = ProcessInfoFlags::from_bits(info.flags).unwrap();
                flags.contains(zx::ProcessInfoFlags::STARTED)
                    && !flags.contains(ProcessInfoFlags::EXITED)
            })
            .unwrap_or_default()
    }

    /// Attempts to clone the server side of the file descriptor.
    pub fn try_clone_fd(&self) -> Result<File, Error> {
        let fd = self.server_pty.try_clone()?;
        Ok(fd)
    }

    /// Sends a message to the shell that the window has been resized.
    pub async fn resize(&self, window_size: WindowSize) -> Result<(), Error> {
        Pty::set_window_size(&self.server_pty, window_size).await?;
        Ok(())
    }

    /// Opens the initial server side of the pty.
    fn open_server_pty() -> Result<File, Error> {
        ftrace::duration!("terminal", "Pty:open_server_pty");
        let server_conn =
            connect_to_service::<DeviceMarker>().context("could not connect to pty service")?;
        let server_chan = server_conn
            .into_channel()
            .or(Err(format_err!("failed to convert pty service into channel")))?;

        // Convert the server into a file descriptor.  We need to do this rather than just using
        // the normal open interface, since otherwise fdio gets confused about the associated event
        // object.  This confusion is caused by how we currently route the pty service through
        // svchost.  Once that routing is gone, this bounce through should be unnecessary.
        let server_pty = fdio::create_fd::<File>(zx::Channel::from(server_chan).into())
            .context("failed to create FD from server PTY")?;
        let fd = server_pty.as_raw_fd();
        let previous = {
            let res = unsafe { libc::fcntl(fd, libc::F_GETFL) };
            if res == -1 {
                Err(std::io::Error::last_os_error()).context("failed to get file status flags")
            } else {
                Ok(res)
            }
        }?;
        let new = previous | libc::O_NONBLOCK;
        if new != previous {
            let res = unsafe { libc::fcntl(fd, libc::F_SETFL, new) };
            let () = if res == -1 {
                Err(std::io::Error::last_os_error()).context("failed to set file status flags")
            } else {
                Ok(())
            }?;
        }
        Ok(server_pty)
    }

    /// Launches the shell process by creating the client side of the pty and then spawning the
    /// shell.
    async fn launch_shell(server_pty: &File, command: &CStr) -> Result<zx::Process, Error> {
        ftrace::duration!("terminal", "Pty:launch_shell");
        let client_pty =
            Pty::open_client_pty(server_pty).await.context("unable to create client_pty")?;
        let process = Pty::spawn_shell_process(client_pty, command)
            .context("unable to spawn shell process")?;

        Ok(process)
    }

    /// Creates a File which is suitable to use as the client side of the Pty.
    async fn open_client_pty(server_pty: &File) -> Result<File, Error> {
        ftrace::duration!("terminal", "Pty:open_client_pty");
        let (client_end, server_end) = fidl::endpoints::create_endpoints()?;

        let server_pty_channel = fdio::clone_channel(server_pty)
            .context("failed to clone channel from server PTY FD")?;
        let server_pty_fidl_channel = fasync::Channel::from_channel(server_pty_channel)
            .context("failed to create FIDL channel from zircon channel")?;

        let device_proxy = DeviceProxy::new(server_pty_fidl_channel);
        let () = device_proxy
            .open_client(0, server_end)
            .await
            .map(zx::Status::ok)
            .context("failed to interact with PTY device")?
            .context("failed to attach PTY to channel")?;

        // convert the client side into a file descriptor. This must be called
        // after the server side has been established.
        let client_pty =
            fdio::create_fd(client_end.into()).context("failed to create FD from client PTY")?;

        Ok(client_pty)
    }

    /// spawns the shell and transfers the client pty to the process.
    fn spawn_shell_process(client_pty: File, command: &CStr) -> Result<zx::Process, Error> {
        ftrace::duration!("terminal", "Pty:spawn_shell_process");
        let process = fdio::spawn_etc(
            &zx::Job::from_handle(zx::Handle::invalid()),
            fdio::SpawnOptions::CLONE_ALL - fdio::SpawnOptions::CLONE_STDIO,
            command,
            &[command],
            None,
            &mut [fdio::SpawnAction::transfer_fd(
                client_pty,
                fdio::fdio_sys::FDIO_FLAG_USE_FOR_STDIO as i32,
            )],
        )
        .map_err(|e| format_err!("failed to spawn shell: {:?}", e))?;

        Ok(process)
    }

    pub async fn set_window_size(
        server_pty: &File,
        mut window_size: WindowSize,
    ) -> Result<(), Error> {
        ftrace::duration!("terminal", "Pty:set_window_size");
        let server_pty_channel = fdio::clone_channel(server_pty)
            .context("failed to clone channel from server PTY FD")?;
        let server_pty_fidl_channel = fasync::Channel::from_channel(server_pty_channel)
            .context("failed to create FIDL channel from zircon channel")?;
        let device_proxy = DeviceProxy::new(server_pty_fidl_channel);

        device_proxy.set_window_size(&mut window_size).await.context("Unable to resize window")?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {futures::io::AsyncWriteExt, zx::AsHandleRef};

    #[fasync::run_singlethreaded(test)]
    async fn can_create_pty() -> Result<(), Error> {
        let _ = Pty::new()?;
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn can_open_client_pty() -> Result<(), Error> {
        let server_pty = Pty::open_server_pty()?;
        let client_pty = Pty::open_client_pty(&server_pty).await?;
        assert!(client_pty.as_raw_fd() > 0);

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn can_open_server_pty() -> Result<(), Error> {
        let server_pty = Pty::open_server_pty()?;
        assert!(server_pty.as_raw_fd() > 0);

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn can_spawn_shell_process() -> Result<(), Error> {
        let server_pty = Pty::open_server_pty()?;
        let process = Pty::launch_shell(&server_pty, &cstr!("/pkg/bin/sh")).await?;

        let mut started = false;
        if let Ok(info) = process.info() {
            started = ProcessInfoFlags::from_bits(info.flags)
                .unwrap()
                .contains(zx::ProcessInfoFlags::STARTED);
        }

        assert_eq!(started, true);

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn shell_process_is_spawned() -> Result<(), Error> {
        let pty = spawn_pty().await?;

        let mut started = false;
        if let Some(process) = &pty.shell_process {
            let info = process.info().unwrap();
            started = ProcessInfoFlags::from_bits(info.flags)
                .unwrap()
                .contains(zx::ProcessInfoFlags::STARTED);
        }
        assert_eq!(started, true);

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn unspawned_shell_process_is_not_running() -> Result<(), Error> {
        let window_size = WindowSize { width: 300 as u32, height: 300 as u32 };
        let pty = Pty::new().unwrap();
        pty.resize(window_size).await?;

        assert_eq!(pty.is_shell_process_running(), false);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn spawned_shell_process_is_running() -> Result<(), Error> {
        let pty = spawn_pty().await?;

        assert_eq!(pty.is_shell_process_running(), true);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn exited_shell_process_is_not_running() -> Result<(), Error> {
        let window_size = WindowSize { width: 300 as u32, height: 300 as u32 };
        let mut pty = Pty::new().unwrap();
        pty.spawn(Some(&cstr!("/pkg/bin/exit_with_code_util"))).await?;
        pty.resize(window_size).await?;

        // Since these tests don't seem to timeout automatically, we must
        // specify a deadline and cannot simply rely on fasync::OnSignals.
        pty.shell_process
            .as_ref()
            .unwrap()
            .wait_handle(
                zx::Signals::PROCESS_TERMINATED,
                zx::Time::after(zx::Duration::from_seconds(60)),
            )
            .expect("shell process did not exit in time");

        assert_eq!(pty.is_shell_process_running(), false);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn can_write_to_shell() -> Result<(), Error> {
        let pty = spawn_pty().await?;
        // EventedFd::new() is unsafe because it can't guarantee the lifetime of
        // the file descriptor passed to it exceeds the lifetime of the EventedFd.
        // Since we're cloning the file when passing it in, the EventedFd
        // effectively owns that file descriptor and thus controls it's lifetime.
        let mut evented_fd = unsafe { fasync::net::EventedFd::new(pty.try_clone_fd()?)? };

        evented_fd.write_all("a".as_bytes()).await?;

        Ok(())
    }

    #[ignore] // TODO(63868): until we figure out why this test is flaking.
    #[fasync::run_singlethreaded(test)]
    async fn shell_process_is_not_running_after_writing_exit() -> Result<(), Error> {
        let pty = spawn_pty().await?;
        // EventedFd::new() is unsafe because it can't guarantee the lifetime of
        // the file descriptor passed to it exceeds the lifetime of the EventedFd.
        // Since we're cloning the file when passing it in, the EventedFd
        // effectively owns that file descriptor and thus controls it's lifetime.
        let mut evented_fd = unsafe { fasync::net::EventedFd::new(pty.try_clone_fd()?)? };

        evented_fd.write_all("exit\n".as_bytes()).await?;

        // Since these tests don't seem to timeout automatically, we must
        // specify a deadline and cannot simply rely on fasync::OnSignals.
        pty.shell_process
            .as_ref()
            .unwrap()
            .wait_handle(
                zx::Signals::PROCESS_TERMINATED,
                zx::Time::after(zx::Duration::from_seconds(60)),
            )
            .expect("shell process did not exit in time");

        assert_eq!(pty.is_shell_process_running(), false);

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn can_resize_window() -> Result<(), Error> {
        let pty = spawn_pty().await?;
        pty.resize(WindowSize { width: 400, height: 400 }).await?;
        Ok(())
    }

    async fn spawn_pty() -> Result<Pty, Error> {
        let window_size = WindowSize { width: 300 as u32, height: 300 as u32 };
        let mut pty = Pty::new().unwrap();
        pty.spawn(Some(&cstr!("/pkg/bin/sh"))).await?;
        pty.resize(window_size).await?;
        Ok(pty)
    }
}
