pipette/
main.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! This is the petri pipette agent, which runs on the guest and executes
5//! commands and other requests from the host.
6
7// UNSAFETY: init.rs requires unsafe for libc calls (fork, mount, reboot, waitpid)
8// on Linux; shutdown.rs requires unsafe for the Windows shutdown API.
9#![cfg_attr(not(any(windows, target_os = "linux")), forbid(unsafe_code))]
10
11#[cfg(any(target_os = "linux", windows))]
12mod agent;
13#[cfg(any(target_os = "linux", windows))]
14mod crash;
15#[cfg(any(target_os = "linux", windows))]
16mod execute;
17#[cfg(target_os = "linux")]
18mod init;
19#[cfg(target_os = "linux")]
20mod mount;
21#[cfg(any(target_os = "linux", windows))]
22mod shutdown;
23#[cfg(any(target_os = "linux", windows))]
24mod trace;
25#[cfg(windows)]
26mod winsvc;
27
28#[cfg(any(target_os = "linux", windows))]
29fn main() -> anyhow::Result<()> {
30    eprintln!("Pipette starting up");
31
32    let hook = std::panic::take_hook();
33    std::panic::set_hook(Box::new(move |info| {
34        eprintln!("Pipette panicked: {}", info);
35        hook(info);
36    }));
37
38    // When running as PID 1 (rdinit=/pipette), perform minimal init duties
39    // before starting the agent.
40    #[cfg(target_os = "linux")]
41    if init::is_pid1() {
42        init::init_as_pid1()?;
43    }
44
45    #[cfg(windows)]
46    if std::env::args().nth(1).as_deref() == Some("--service") {
47        return winsvc::start_service();
48    }
49
50    pal_async::DefaultPool::run_with(async |driver| {
51        loop {
52            let agent = agent::Agent::new(driver.clone()).await?;
53            agent.run().await?;
54            eprintln!("Pipette disconnected, reconnecting...");
55        }
56    })
57}
58
59#[cfg(not(any(target_os = "linux", windows)))]
60fn main() -> anyhow::Result<()> {
61    anyhow::bail!("unsupported platform");
62}