# 機能設計書 78-setup_shell

## 概要

本ドキュメントは、Oh My Zshインストールスクリプト（tools/install.sh）内の`setup_shell`関数の機能設計について記述する。

### 本機能の処理概要

`setup_shell`関数は、ユーザーのデフォルトシェルをzshに変更する処理を担当する。`chsh`コマンドを使用してログインシェルを変更し、変更前のシェル情報をバックアップファイルに保存する。sudo権限が必要な場合は適切にsudoを使用し、Termux環境では特別な処理を行う。

**業務上の目的・背景**：Oh My Zshを最大限に活用するには、デフォルトシェルがzshである必要がある。本関数は、ユーザーに確認を取りながら安全にシェルを変更し、問題が発生した場合に元に戻せるよう変更前の状態を保存する。

**機能の利用シーン**：
- install.shによるOh My Zshの新規インストール時
- CHSH=noを指定しない場合（デフォルトで実行）
- ユーザーが確認ダイアログでY/yまたはEnterを選択した場合

**主要な処理内容**：
1. CHSH=noまたは既にzshがデフォルトシェルの場合はスキップ
2. chshコマンドの存在確認
3. ユーザーにシェル変更の確認を求める
4. Termux環境の検出と特別処理
5. /etc/shellsからzshのパスを取得
6. 現在のシェル情報を.shell.pre-oh-my-zshに保存
7. chshコマンドでシェルを変更（必要に応じてsudo使用）
8. 結果の確認と$SHELL変数の更新

**関連システム・外部連携**：chsh（シェル変更）、sudo（権限昇格）、/etc/shells（有効シェル一覧）。

**権限による制御**：chshコマンドの実行にはsudo権限が必要な場合がある。user_can_sudo()で事前に確認。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | install.sh | 主画面 | Oh My Zshインストールの一部としてデフォルトシェルを変更 |

## 機能種別

システム設定変更

## 入力仕様

### 入力パラメータ

setup_shell関数自体は引数を取らないが、以下のグローバル変数を参照する。

| 変数名 | 型 | 必須 | 説明 |
|--------|-----|-----|------|
| $CHSH | string | No | "no"でシェル変更をスキップ |
| $SHELL | string | Yes | 現在のログインシェル |
| $USER | string | Yes | ユーザー名 |
| $zdot | string | Yes | dotfilesディレクトリ |
| $PREFIX | string | No | Termux環境の検出に使用 |

### 入力データソース

- グローバル変数（install.shで設定）
- /etc/shells（有効シェル一覧）
- ユーザー入力（確認ダイアログ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| .shell.pre-oh-my-zsh | file | 変更前のシェル情報 |
| シェル変更 | system | /etc/passwdのログインシェル |

### 出力先

- $zdot/.shell.pre-oh-my-zsh
- システムのユーザーデータベース（/etc/passwd等）

## 処理フロー

### 処理シーケンス

```
1. スキップ条件確認
   └─ CHSH=no または 既にzshがデフォルト
2. chshコマンド存在確認
   └─ なければ手動変更を促すメッセージ
3. 確認ダイアログ表示
   └─ "Do you want to change your default shell to zsh?"
4. Termux環境確認
   └─ $PREFIXに"com.termux"が含まれるか
5. zshパス取得
   └─ command -v zsh または /etc/shellsから取得
6. 現在シェルのバックアップ
   └─ $SHELLを.shell.pre-oh-my-zshに保存
7. chsh実行
   └─ sudo使用可能時: sudo -k chsh -s "$zsh" "$USER"
   └─ 通常時: chsh -s "$zsh" "$USER"
8. 結果確認
   └─ 成功時: $SHELL変数を更新
   └─ 失敗時: エラーメッセージ表示
```

### フローチャート

```mermaid
flowchart TD
    A[setup_shell開始] --> B{CHSH=no?}
    B -->|Yes| C[return]
    B -->|No| D{既にzshがデフォルト?}
    D -->|Yes| C
    D -->|No| E{chsh存在?}
    E -->|No| F[手動変更メッセージ]
    F --> C
    E -->|Yes| G[確認ダイアログ]
    G --> H{Y/Enter?}
    H -->|No| I[スキップメッセージ]
    I --> C
    H -->|Yes| J{Termux?}
    J -->|Yes| K[zsh=zsh]
    J -->|No| L[/etc/shellsからzshパス取得]
    K --> M[現在シェルをバックアップ]
    L --> M
    M --> N{user_can_sudo?}
    N -->|Yes| O[sudo chsh]
    N -->|No| P[chsh]
    O --> Q{成功?}
    P --> Q
    Q -->|Yes| R[$SHELL更新]
    Q -->|No| S[エラーメッセージ]
    R --> T[終了]
    S --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-01 | zsh必須確認 | 既にzshがデフォルトならスキップ | 常時 |
| BR-78-02 | chsh必須 | chshコマンドがなければ手動変更を促す | chsh不存在時 |
| BR-78-03 | バックアップ必須 | 変更前のシェルを保存 | シェル変更前 |
| BR-78-04 | sudo優先 | sudo使用可能時はsudo経由でchsh | sudo利用可能時 |
| BR-78-05 | パスワード要求 | sudo -kでキャッシュをクリアしパスワード要求 | sudo使用時 |
| BR-78-06 | Termux特別処理 | Termux環境ではzsh直接指定 | Termux環境時 |

### 計算ロジック

```
# zshパス取得ロジック
if Termux:
    zsh = "zsh"
elif command -v zsh in /etc/shells:
    zsh = command -v zsh
elif /etc/shells contains zsh:
    zsh = (last match from /etc/shells)
else:
    error
```

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし（システムコマンドchshによるユーザーデータベース変更）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | chsh不存在 | システムにchshがない | 手動でシェルを変更 |
| N/A | zsh未検出 | /etc/shellsにzshがない | zshをインストールして再実行 |
| N/A | chsh失敗 | chshコマンドが失敗 | 手動でシェルを変更 |

### リトライ仕様

リトライは不要（手動で再実行）

## トランザクション仕様

- 変更前のシェルはバックアップファイルに保存
- uninstall.shで元のシェルに復元可能

## パフォーマンス要件

即時完了（システムコマンド実行）

## セキュリティ考慮事項

- sudo -kでパスワードキャッシュをクリアし、必ずパスワードを要求
- user_can_sudo()でsudo権限を事前確認
- /etc/shellsに登録されたzshのみを使用

## 備考

- Google Cloud Shellなどパスワードなしのsudo環境に対応
- Solus OSの/usr/share/defaults/etc/shellsにも対応
- Termuxはchshが使用できないため特別処理

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 関数の全体構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | install.sh | `tools/install.sh` | setup_shell関数の定義（396-490行目） |

**読解のコツ**: POSIXシェル互換スクリプト。`basename -- "$SHELL"`で現在のシェル名を取得。`case "$PREFIX" in *com.termux*)`でTermux検出。

**主要処理フロー**:
- **398-400行目**: CHSH=no時のスキップ
- **403-405行目**: 既にzshがデフォルト時のスキップ
- **407-414行目**: chshコマンド存在確認
- **416-426行目**: 確認ダイアログ
- **428-432行目**: Termux環境検出
- **434-454行目**: zshパス取得
- **458-462行目**: 現在シェルのバックアップ
- **475-479行目**: chsh実行

#### Step 2: user_can_sudo関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | install.sh | `tools/install.sh` | user_can_sudo関数（88-114行目） |

**主要処理フロー**:
- **90行目**: `command_exists sudo || return 1` - sudo存在確認
- **92-94行目**: Termux環境ではsudo不可
- **96-113行目**: `sudo -n -v`でパスワードなしsudo確認
- **113行目**: "may not run sudo"を含まなければsudo可能

#### Step 3: zshパス取得ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | install.sh | `tools/install.sh` | zshパス取得（434-454行目） |

**主要処理フロー**:
- **436-440行目**: /etc/shellsファイルの場所確認（Solus OS対応含む）
- **448行目**: `command -v zsh`と/etc/shellsの照合
- **449行目**: /etc/shellsから`^/.*/zsh$`パターンで取得

### プログラム呼び出し階層図

```
setup_shell() (tools/install.sh:396-490)
    │
    ├─ basename -- "$SHELL" (現在シェル確認)
    │
    ├─ command_exists chsh
    │
    ├─ read -r opt (ユーザー確認)
    │
    ├─ [Termux検出] case "$PREFIX" in *com.termux*
    │
    ├─ command -v zsh
    │
    ├─ grep '^/.*/zsh$' "$shells_file"
    │
    ├─ echo "$SHELL" > "$zdot/.shell.pre-oh-my-zsh"
    │
    ├─ user_can_sudo() (tools/install.sh:88-114)
    │      ├─ command_exists sudo
    │      └─ sudo -n -v
    │
    └─ chsh -s "$zsh" "$USER"
           └─ (または sudo -k chsh -s "$zsh" "$USER")
```

### データフロー図

```
[入力]                          [処理]                           [出力]

$CHSH ─────────────────────▶ スキップ判定
                                 │
$SHELL ────────────────────────▶│
(現在のシェル)                   │
                                 │
ユーザー入力 ──────────────────▶│──▶ 確認ダイアログ
                                 │
$PREFIX ───────────────────────▶│──▶ Termux検出
                                 │
/etc/shells ───────────────────▶│──▶ zshパス取得
                                 │
                                 ▼
                           バックアップ ─────────▶ .shell.pre-oh-my-zsh
                                 │
                                 ▼
                           chsh -s $zsh ─────────▶ /etc/passwd
                                 │                  (シェル変更)
                                 ▼
                           $SHELL = $zsh
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| install.sh | `tools/install.sh` | ソース | setup_shell関数の定義元 |
| /etc/shells | システム | 設定 | 有効なシェル一覧 |
| /usr/share/defaults/etc/shells | システム(Solus) | 設定 | Solus OSの有効シェル一覧 |
| uninstall.sh | `tools/uninstall.sh` | ソース | .shell.pre-oh-my-zshを使用してシェル復元 |
| .shell.pre-oh-my-zsh | `$zdot/` | バックアップ | 変更前のシェル情報 |
