🐚

Macのターミナルはシェルをどう探すか

2021/07/25に公開

ターミナルエミュレータを起動すると、ログインシェルが実行される(そう実装されていれば)。macOSのいくつかのターミナルエミュレータがどうやってログインシェルを探しているかを調べた。

login(1)

Terminal.app や iTerm2 は自分でシェルを探さずに login(1) を実行する。

$ login -fp $USER

これによりログインシェルが実行される。

% 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

dscl(1)

dscl(1) でディレクトリサービスから情報を取得できる。UserShellを指定するとログインシェルが得られる。

$ dscl . read /Users/$USER UserShell
UserShell: /bin/bash

Discussion