// Copyright 2018 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.
library fuchsia.process;

using fuchsia.io;
using zx;

/// Information about a handle provided to a process at startup.
///
/// Processes are given a set of initial handles as part of the bootstrapping
/// sequence. Some of these handles are associated with zx.procarg identifiers
/// that designate their intended use by the new process.
///
/// This structure represents one such handle and its associated zx.procarg
/// identifier.
type HandleInfo = resource struct {
    /// The handle to use for this process argument.
    handle zx.handle;

    /// Process argument identifier.
    ///
    /// See <zircon/processargs.h> for definitions of well-known process
    /// arguments.
    id zx.procarg;
};

/// A namespace entry provided to a process at startup.
///
/// Processes are given a set of initial handles as part of the bootstrapping
/// sequence. Some of these handles are associated with paths that designate
/// their intended use by the new process as namespace entries.
///
/// This structure represents one such handle and its associated namespace path.
type NameInfo = resource struct {
    /// Path at which to install the associated directory.
    ///
    /// Must be an absolute path (i.e., start with '/').
    path string:fuchsia.io.MAX_PATH;

    /// The associated directory.
    directory client_end:fuchsia.io.Directory;
};

/// The information needed to launch a process.
type LaunchInfo = resource struct {
    /// The executable to run in the process.
    executable zx.handle:VMO;

    /// The job in which to create the process.
    job zx.handle:JOB;

    /// The name to assign to the created process.
    name string:zx.MAX_NAME_LEN;
};

/// The information required to start a process.
///
/// To start the process, call `zx_process_start` with the arguments provided.
type ProcessStartData = resource struct {
    /// The process that was created.
    process zx.handle:PROCESS;

    /// The vmar object that was created when the process was created.
    ///
    /// See <https://fuchsia.dev/fuchsia-src/reference/syscalls/process_create.md>.
    root_vmar zx.handle:VMAR;

    /// The initial thread for the process.
    ///
    /// Should be passed to `zx_process_start` when starting the process.
    thread zx.handle:THREAD;

    /// The address of the initial entry point in the process.
    ///
    /// Should be passed to `zx_process_start` when starting the process.
    entry zx.vaddr;

    /// The stack pointer value for the initial thread of the process.
    ///
    /// Should be passed to `zx_process_start` when starting the process.
    stack zx.vaddr;

    /// The bootstrap channel to pass to the process on startup.
    ///
    /// Should be passed to `zx_process_start` when starting the process.
    bootstrap zx.handle:CHANNEL;

    /// The base address of the vDSO to pass to the process on startup.
    ///
    /// Should be passed to `zx_process_start` when starting the process.
    vdso_base zx.vaddr;

    /// The base load address of the ELF file loaded.
    ///
    /// Most often used by debuggers or other tools that inspect the process.
    base zx.vaddr;
};

// TODO(fxbug.dev/37281): replace with built-in constant
const MAX uint32 = 0xFFFFFFFF;

/// A low-level interface for launching processes.
///
/// This interface is used for manually assembling a process. The caller supplies
/// all the capabilities for the newly created process.
///
/// That create processes typically use `fdio_spawn` or `fdio_spawn_etc` rather
/// than using this interface directly. The `fdio_spawn` and `fdio_spawn_etc`
/// functions are implemented using this interface.
///
/// Debuggers and other clients that need to create processes in a suspended
/// state often use this interface directly. These clients use the
/// `CreateWithoutStarting` method to create the process without actually
/// starting it.
@discoverable
protocol Launcher {
    /// Creates and starts the process described by `info`.
    ///
    /// After processing this message, the `Launcher` is reset to its initial
    /// state and is ready to launch another process.
    ///
    /// `process` is present if, and only if, `status` is `ZX_OK`.
    Launch(resource struct {
        info LaunchInfo;
    }) -> (resource struct {
        status zx.status;
        process zx.handle:<PROCESS, optional>;
    });

    /// Creates the process described by `info` but does not start it.
    ///
    /// After processing this message, the `Launcher` is reset to its initial
    /// state and is ready to launch another process.
    ///
    /// The caller is responsible for calling `zx_process_start` using the data
    /// in `ProcessStartData` to actually start the process.
    ///
    /// `data` is present if, and only if, `status` is `ZX_OK`.
    CreateWithoutStarting(resource struct {
        info LaunchInfo;
    }) -> (resource struct {
        status zx.status;
        data box<ProcessStartData>;
    });

    /// Adds the given arguments to the command-line for the process.
    ///
    /// Calling this method multiple times concatenates the arguments.
    AddArgs(struct {
        args vector<vector<uint8>:MAX>:MAX;
    });

    /// Adds the given variables to the environment variables for the process.
    ///
    /// Calling this method multiple times concatenates the variables.
    AddEnvirons(struct {
        environ vector<vector<uint8>:MAX>:MAX;
    });

    /// Adds the given names to the namespace for the process.
    ///
    /// The paths in the namespace must be non-overlapping. See
    /// <https://fuchsia.dev/fuchsia-src/concepts/process/namespaces> for details.
    ///
    /// Calling this method multiple times concatenates the names.
    AddNames(resource struct {
        names vector<NameInfo>:MAX;
    });

    /// Adds the given handles to the startup handles for the process.
    ///
    /// Calling this method multiple times concatenates the handles.
    AddHandles(resource struct {
        handles vector<HandleInfo>:MAX;
    });
};
