@@ -306,6 +306,10 @@ fn main() {
Task::ready(())
} else {
app.background_executor().spawn(async {
+ #[cfg(unix)]
+ {
+ load_shell_from_passwd().await.log_err();
+ }
load_login_shell_environment().await.log_err();
})
};
@@ -678,6 +682,56 @@ fn init_stdout_logger() {
})
.init();
}
+
+#[cfg(unix)]
+async fn load_shell_from_passwd() -> Result<()> {
+ let buflen = match unsafe { libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) } {
+ n if n < 0 => 1024,
+ n => n as usize,
+ };
+ let mut buffer = Vec::with_capacity(buflen);
+
+ let mut pwd: std::mem::MaybeUninit<libc::passwd> = std::mem::MaybeUninit::uninit();
+ let mut result: *mut libc::passwd = std::ptr::null_mut();
+
+ let uid = unsafe { libc::getuid() };
+ let status = unsafe {
+ libc::getpwuid_r(
+ uid,
+ pwd.as_mut_ptr(),
+ buffer.as_mut_ptr() as *mut libc::c_char,
+ buflen,
+ &mut result,
+ )
+ };
+ let entry = unsafe { pwd.assume_init() };
+
+ anyhow::ensure!(
+ status == 0,
+ "call to getpwuid_r failed. uid: {}, status: {}",
+ uid,
+ status
+ );
+ anyhow::ensure!(!result.is_null(), "passwd entry for uid {} not found", uid);
+ anyhow::ensure!(
+ entry.pw_uid == uid,
+ "passwd entry has different uid ({}) than getuid ({}) returned",
+ entry.pw_uid,
+ uid,
+ );
+
+ let shell = unsafe { std::ffi::CStr::from_ptr(entry.pw_shell).to_str().unwrap() };
+ if env::var("SHELL").map_or(true, |shell_env| shell_env != shell) {
+ log::info!(
+ "updating SHELL environment variable to value from passwd entry: {:?}",
+ shell,
+ );
+ env::set_var("SHELL", shell);
+ }
+
+ Ok(())
+}
+
async fn load_login_shell_environment() -> Result<()> {
let marker = "ZED_LOGIN_SHELL_START";
let shell = env::var("SHELL").context(