🐚
Macのターミナルはシェルをどう探すか
ターミナルエミュレータを起動すると、ログインシェルが実行される(そう実装されていれば)。macOSのいくつかのターミナルエミュレータがどうやってログインシェルを探しているかを調べた。
login(1)
Terminal.app や iTerm2 は自分でシェルを探さずに login(1) を実行する。
$ login -fp $USER
これによりログインシェルが実行される。
- iTerm2 の実装: https://github.com/gnachman/iTerm2/blob/3e1ecb9d4c4ef758bef0e4b4a8441a05f7568217/sources/ITAddressBookMgr.m#L641
- Terminal.app については、ps(1) でシェルの親プロセスを確認するとわかる
% ps -f $$
UID PID PPID C STIME TTY TIME CMD
501 23221 23220 0 12:44AM ttys004 0:00.04 -zsh
% ps -f 23220
UID PID PPID C STIME TTY TIME CMD
0 23220 23219 0 12:44AM ttys004 0:00.01 login -pf yoichi
% ps -f 23219
UID PID PPID C STIME TTY TIME CMD
501 23219 1 0 12:44AM ?? 0:00.70 /System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
getpwuid(3) / getpwuid_r(3)
libcの関数 getpwuid(3) を呼び出して得られる passwd 構造体のメンバー pw_shell にログインシェルが記載されている。
サンプルコード:
print_login_shell.c
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
#include <uuid/uuid.h>
int main()
{
struct passwd *pw = getpwuid(geteuid());
if (pw == NULL) return 1;
printf("%s\n", pw->pw_shell);
return 0;
}
実行例:
$ gcc -o print_login_shell print_login_shell.c
$ ./print_login_shell
/bin/bash
- xterm は getpwuid(3) を呼び出している: https://github.com/ThomasDickey/xterm-snapshots/blob/b2ecdc26094793725db0353b0699e4d31446351e/main.c#L5029
- WezTerm は Rust の libc::getpwuid 経由で: https://github.com/wez/wezterm/blob/fc2f7b83d29a4c4b3e8a09834c95d9d7f74943c2/pty/src/cmdbuilder.rs#L180
- Alacritty は Rust の libc::getpwuid_r 経由で: https://github.com/alacritty/alacritty/blob/c69067e1e92d70fd9088195460a320c914330d74/alacritty_terminal/src/tty/unix.rs#L130
- Kitty は Python の pwd.getpwuid 経由で: https://github.com/kovidgoyal/kitty/blob/630379651eb8080e3e96327137df741ed5e67ed5/kitty/constants.py#L131
dscl(1)
dscl(1) でディレクトリサービスから情報を取得できる。UserShellを指定するとログインシェルが得られる。
$ dscl . read /Users/$USER UserShell
UserShell: /bin/bash
Discussion