Fallback to SHELL instead of passwd if present

Instead of just always falling back to the shell specified in the passwd
file when no config or cli shell was specified, Alacritty will not first
look at the `$SHELL` environment variable. If this is unset, it will
still read the passwd file.

Since macOS is a bit peculiar and does not set the `$SHELL` environment
variable by default, it is set manually to the shell used by Alacritty
while any existing `$SHELL` variables are ignored. This matches the
behavior of iTerm and Terminal.app.

Co-authored-by: Christian Duerr <contact@christianduerr.com>
This commit is contained in:
Mattbazooka 2020-07-14 19:03:36 +10:00 committed by GitHub
parent 68209e88fd
commit 76a4c373da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 27 deletions

View File

@ -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

View File

@ -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<C>(config: &Config<C>, size: &SizeInfo, window_id: Option<usize>) -> 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<C>(config: &Config<C>, size: &SizeInfo, window_id: Option<usize>) ->
}
}
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<C>(config: &Config<C>, size: &SizeInfo, window_id: Option<usize>) ->
// 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));
}