-
Notifications
You must be signed in to change notification settings - Fork 936
/
Copy pathrustup-init.rs
124 lines (112 loc) · 3.76 KB
/
rustup-init.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! The main rustup commandline application
//!
//! The rustup binary is a chimera, changing its behavior based on the
//! name of the binary. This is used most prominently to enable
//! rustup's tool 'proxies' - that is, rustup itself and the rustup
//! proxies are the same binary; when the binary is called 'rustup' or
//! 'rustup.exe' rustup behaves like the rustup commandline
//! application; when it is called 'rustc' it behaves as a proxy to
//! 'rustc'.
//!
//! This scheme is further used to distinguish the rustup installer,
//! called 'rustup-init' which is again just the rustup binary under a
//! different name.
#![recursion_limit = "1024"]
#![feature(rt)]
use std::path::PathBuf;
#[cfg(feature = "rt")]
use std::rt;
use cfg_if::cfg_if;
use rs_tracing::*;
use rustup::cli::common;
use rustup::cli::errors::*;
#[cfg(feature = "rt")]
use rustup::cli::log;
use rustup::cli::proxy_mode;
use rustup::cli::rustup_mode;
#[cfg(windows)]
use rustup::cli::self_update;
use rustup::cli::setup_mode;
use rustup::currentprocess::{process, with, OSProcess};
use rustup::env_var::RUST_RECURSION_COUNT_MAX;
use rustup::utils::utils;
fn main() {
let process = OSProcess::default();
with(Box::new(process), || match run_rustup() {
Err(ref e) => {
common::report_error(e);
std::process::exit(1);
}
Ok(utils::ExitCode(c)) => std::process::exit(c),
});
}
fn run_rustup() -> Result<utils::ExitCode> {
#[cfg(feature = "rt")]
{
let _ = rt::at_exit(log::on_quit_log);
}
if let Ok(dir) = process().var("RUSTUP_TRACE_DIR") {
open_trace_file!(dir)?;
}
let result = run_rustup_inner();
if process().var("RUSTUP_TRACE_DIR").is_ok() {
close_trace_file!();
}
result
}
fn run_rustup_inner() -> Result<utils::ExitCode> {
// Guard against infinite proxy recursion. This mostly happens due to
// bugs in rustup.
do_recursion_guard()?;
// Before we do anything else, ensure we know where we are and who we
// are because otherwise we cannot proceed usefully.
process().current_dir()?;
utils::current_exe()?;
// The name of arg0 determines how the program is going to behave
let arg0 = match process().var("RUSTUP_FORCE_ARG0") {
Ok(v) => Some(v),
Err(_) => process().args().next(),
}
.map(PathBuf::from);
let name = arg0
.as_ref()
.and_then(|a| a.file_stem())
.and_then(std::ffi::OsStr::to_str);
match name {
Some("rustup") => rustup_mode::main(),
Some(n) if n.starts_with("rustup-setup") || n.starts_with("rustup-init") => {
// NB: The above check is only for the prefix of the file
// name. Browsers rename duplicates to
// e.g. rustup-setup(2), and this allows all variations
// to work.
setup_mode::main()
}
Some(n) if n.starts_with("rustup-gc-") => {
// This is the final uninstallation stage on windows where
// rustup deletes its own exe
cfg_if! {
if #[cfg(windows)] {
self_update::complete_windows_uninstall()
} else {
unreachable!("Attempted to use Windows-specific code on a non-Windows platform. Aborting.")
}
}
}
Some(_) => proxy_mode::main(),
None => {
// Weird case. No arg0, or it's unparsable.
Err(ErrorKind::NoExeName.into())
}
}
}
fn do_recursion_guard() -> Result<()> {
let recursion_count = process()
.var("RUST_RECURSION_COUNT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(0);
if recursion_count > RUST_RECURSION_COUNT_MAX {
return Err(ErrorKind::InfiniteRecursion.into());
}
Ok(())
}