diff --git a/CHANGELOG.md b/CHANGELOG.md index f1cea655..e773d4e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for `gopher` and `gemini` URLs - Unicode 13 support - Option to run command on bell which can be set in `bell.command` +- Fallback to program specified in `$SHELL` variable on Linux/BSD if it is present ### Changed diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index b6807cc2..b373ada2 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -1,18 +1,7 @@ //! TTY related functionality. -use crate::config::{Config, Program}; -use crate::event::OnResize; -use crate::term::SizeInfo; -use crate::tty::{ChildEvent, EventedPty, EventedReadWrite}; - -use libc::{self, c_int, pid_t, winsize, TIOCSCTTY}; -use log::error; -use nix::pty::openpty; -#[cfg(any(target_os = "linux", target_os = "macos"))] -use nix::sys::termios::{self, InputFlags, SetArg}; -use signal_hook::{self as sighook, iterator::Signals}; - -use mio::unix::EventedFd; +use std::borrow::Cow; +use std::env; use std::ffi::CStr; use std::fs::File; use std::io; @@ -25,6 +14,19 @@ use std::process::{Child, Command, Stdio}; use std::ptr; use std::sync::atomic::{AtomicUsize, Ordering}; +use libc::{self, c_int, pid_t, winsize, TIOCSCTTY}; +use log::error; +use mio::unix::EventedFd; +use nix::pty::openpty; +#[cfg(any(target_os = "linux", target_os = "macos"))] +use nix::sys::termios::{self, InputFlags, SetArg}; +use signal_hook::{self as sighook, iterator::Signals}; + +use crate::config::{Config, Program}; +use crate::event::OnResize; +use crate::term::SizeInfo; +use crate::tty::{ChildEvent, EventedPty, EventedReadWrite}; + /// Process ID of child process. /// /// Necessary to put this in static storage for `SIGCHLD` to have access. @@ -128,13 +130,22 @@ pub struct Pty { signals_token: mio::Token, } +#[cfg(target_os = "macos")] +fn default_shell(pw: &Passwd<'_>) -> Program { + let shell_name = pw.shell.rsplit('/').next().unwrap(); + let argv = vec![String::from("-c"), format!("exec -a -{} {}", shell_name, pw.shell)]; + + Program::WithArgs { program: "/bin/bash".to_owned(), args: argv } +} + +#[cfg(not(target_os = "macos"))] +fn default_shell(pw: &Passwd<'_>) -> Program { + Program::Just(env::var("SHELL").unwrap_or_else(|_| pw.shell.to_owned())) +} + /// Create a new TTY and return a handle to interact with it. pub fn new(config: &Config, size: &SizeInfo, window_id: Option) -> Pty { - let win_size = size.to_winsize(); - let mut buf = [0; 1024]; - let pw = get_pw_entry(&mut buf); - - let (master, slave) = make_pty(win_size); + let (master, slave) = make_pty(size.to_winsize()); #[cfg(any(target_os = "linux", target_os = "macos"))] { @@ -145,17 +156,15 @@ pub fn new(config: &Config, size: &SizeInfo, window_id: Option) -> } } - let default_shell = if cfg!(target_os = "macos") { - let shell_name = pw.shell.rsplit('/').next().unwrap(); - let argv = vec![String::from("-c"), format!("exec -a -{} {}", shell_name, pw.shell)]; + let mut buf = [0; 1024]; + let pw = get_pw_entry(&mut buf); - Program::WithArgs { program: "/bin/bash".to_owned(), args: argv } - } else { - Program::Just(pw.shell.to_owned()) + let shell = match config.shell.as_ref() { + Some(shell) => Cow::Borrowed(shell), + None => Cow::Owned(default_shell(&pw)), }; - let shell = config.shell.as_ref().unwrap_or(&default_shell); - let mut builder = Command::new(&*shell.program()); + let mut builder = Command::new(shell.program()); for arg in shell.args() { builder.arg(arg); } @@ -171,9 +180,12 @@ pub fn new(config: &Config, size: &SizeInfo, window_id: Option) -> // Setup shell environment. builder.env("LOGNAME", pw.name); builder.env("USER", pw.name); - builder.env("SHELL", pw.shell); builder.env("HOME", pw.dir); + // Set $SHELL environment variable on macOS, since login does not do it for us. + #[cfg(target_os = "macos")] + builder.env("SHELL", config.shell.as_ref().map(|sh| sh.program()).unwrap_or(pw.shell)); + if let Some(window_id) = window_id { builder.env("WINDOWID", format!("{}", window_id)); }