# 帳票設計書 1-ac - 接続時間アカウンティングレポート

## 概要

本ドキュメントは、FreeBSDシステムにおけるユーザー接続時間アカウンティングレポート(ac)の帳票設計書である。acコマンドはwtmpxログファイルを読み取り、ユーザーごとまたは日ごとの接続時間（ログイン時間）を集計し、テキスト形式のレポートとして標準出力に出力する。

### 本帳票の処理概要

**業務上の目的・背景**：システム管理者がユーザーのログイン時間を把握し、システム利用状況の監査やリソース配分の最適化を行うために必要なレポートである。組織のセキュリティポリシーや利用規約の遵守状況を確認する際にも利用される。

**帳票の利用シーン**：システム管理者が定期的なシステム利用状況の確認を行う場合、特定ユーザーの接続時間を調査する場合、セキュリティ監査においてログイン履歴を分析する場合に利用される。

**主要な出力内容**：
1. ユーザーごとの接続時間（小数点以下2桁の時間単位）
2. 日ごとの接続時間合計（-dオプション指定時）
3. 全体の合計接続時間

**帳票の出力タイミング**：システム管理者がコマンドラインからacコマンドを実行した時点で即時出力される。cronジョブ等での定期実行も可能。

**帳票の利用者**：システム管理者、セキュリティ監査担当者、運用チーム。

## 帳票種別

集計表（テキスト形式の統計レポート）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | ターミナル/コンソール | N/A | `ac [-dp] [-c console] [-t tty] [-w wtmp] [users ...]` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A（コンソール出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力へ出力、リダイレクトにより任意ファイルへ保存可） |
| 出力方法 | 標準出力への直接出力 |
| 文字コード | ロケール依存（LC_TIME設定に従う） |

## 帳票レイアウト

### レイアウト概要

帳票はタブ区切りのテキスト形式で、各行にユーザー名と接続時間を表示する。最終行に合計接続時間を出力する。

```
┌─────────────────────────────────────┐
│   ユーザーごとの接続時間（-p指定時）   │
│   または                             │
│   日ごとの接続時間合計（-d指定時）     │
├─────────────────────────────────────┤
│   合計接続時間                        │
└─────────────────────────────────────┘
```

### 明細部（ユーザー別モード: -pオプション指定時）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | ユーザー名 | ログインユーザー名 | utmpx.ut_user | 左詰め文字列 | ut_user構造体サイズ |
| 2 | 接続時間 | 合計接続時間 | 計算値（ログアウト時刻 - ログイン時刻の累計） | 小数点2桁の時間（hours） | 8桁 |

### 明細部（日別モード: -dオプション指定時）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | 日付 | 対象日 | utmpx.ut_tv | "月 日 total" または "日 月 total" | 可変 |
| 2 | 日別合計時間 | その日の全ユーザー合計接続時間 | 計算値 | 小数点2桁の時間（hours） | 11桁 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 合計ラベル | "total" | 固定文字列 | 左詰め |
| 2 | 合計接続時間 | 全期間の合計接続時間 | Total変数（timeval） | 小数点2桁の時間（hours） |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ユーザー指定 | コマンドライン引数でユーザー名を指定すると、そのユーザーのみ集計 | No |
| TTY指定（-t） | 特定のTTYデバイスに限定した集計 | No |
| wtmpファイル指定（-w） | デフォルト以外のwtmpファイルを読み取り対象とする | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ユーザー名 | 昇順（アルファベット順、update_user関数で挿入ソート） |

### 改ページ条件

改ページ機能なし（テキストストリーム出力）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| utmpxログファイル（UTXDB_LOG） | ユーザーのログイン/ログアウト履歴の取得 | 時系列順に読み取り |

### テーブル別参照項目詳細

#### utmpxログファイル

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| ut_user | ユーザー名 | USER_PROCESSタイプのレコード | ログインユーザー名 |
| ut_tv | ログイン/ログアウト時刻 | 全レコード | timeval構造体 |
| ut_type | レコード種別判定 | BOOT_TIME, SHUTDOWN_TIME, USER_PROCESS, DEAD_PROCESS | 処理分岐に使用 |
| ut_id | セッション識別 | DEAD_PROCESSレコードとの照合 | ログアウト判定に使用 |
| ut_line | TTYデバイス名 | -tオプション指定時のフィルタリング | TTY指定フィルタ |
| ut_host | ホスト名 | pts接続の判定 | 空文字列の場合は非実ログインとして除外 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 接続時間（時間） | (tv_sec値) / 3600.0 | 小数点以下2桁（%.2f） | printf("%.2f")で出力 |
| ユーザー別接続時間 | ログアウト時刻.tv - ログイン時刻.tv の累計 | timeval加算（秒+マイクロ秒） | timeradd/timersub使用 |
| 日別合計時間 | 当日のユーザー別接続時間の合計 | timeval加算 | show_today関数で計算 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[オプション解析 getopt]
    B --> C{-wオプション?}
    C -->|Yes| D[指定wtmpファイルをオープン]
    C -->|No| E[デフォルトUTXDB_LOGをオープン]
    D --> F[ac関数: utmpxレコード順次読み取り]
    E --> F
    F --> G{レコードタイプ判定}
    G -->|USER_PROCESS| H[log_in: セッション記録開始]
    G -->|DEAD_PROCESS| I[log_out: セッション記録終了・時間計算]
    G -->|BOOT/SHUTDOWN| J[log_out: 全セッション終了]
    G -->|OLD/NEW_TIME| K[時計変更補正]
    H --> L{日替わり? -d指定時}
    I --> L
    J --> L
    K --> L
    L -->|Yes| M[show_today: 前日分出力]
    L -->|No| N[次レコード読み取り]
    M --> N
    N --> O{全レコード処理完了?}
    O -->|No| F
    O -->|Yes| P{出力モード判定}
    P -->|-d| Q[show_today: 最終日分出力]
    P -->|-p| R[show_users: ユーザー別出力]
    P -->|default| S[show: total出力]
    Q --> T[終了]
    R --> S
    S --> T
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| wtmpファイルオープン失敗 | setutxdb()が失敗 | err(1, "%s", file) | wtmpファイルの存在・パーミッション確認 |
| メモリ確保失敗 | malloc()がNULL返却 | errx(1, "malloc failed") | メモリ不足の解消 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | wtmpファイルサイズに依存（通常数千～数万レコード） |
| 目標出力時間 | wtmpファイルの逐次読み取りのため、ファイルサイズに比例 |
| 同時出力数上限 | N/A（シングルプロセス実行） |

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

- wtmpファイルへの読み取り権限が必要（通常root権限またはutmpグループ）
- ユーザーのログイン時間情報はプライバシーに関わるため、アクセス制御が必要
- -wオプションで任意ファイルを指定可能なため、ファイルパスの妥当性はOS側のパーミッションに委ねている

## 備考

- -dと-pは排他的（-d指定時は-pが無効化される: `Flags &= ~AC_P`）
- pts/接続の場合、ut_hostが空でないことがログイン判定の条件（ac.c 464行目）
- 時計変更（OLD_TIME/NEW_TIME）がある場合、既存セッションの開始時刻が補正される

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

utmpxレコード構造と、acコマンドが内部で使用するリンクドリスト構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ac.c | `usr.sbin/ac/ac.c` | 49-76行目: utmpx_entry, user_entry, tty_entryの3つの構造体定義。SLIST（単方向リンクドリスト）で管理される。 |

**読解のコツ**: `SLIST_*`マクロはFreeBSDの`<sys/queue.h>`で定義されたリスト操作マクロ。SLIST_FOREACH, SLIST_INSERT_HEADなどの使い方を把握すること。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ac.c | `usr.sbin/ac/ac.c` | 204-253行目: main関数。getoptでオプション解析後、ac()関数を呼び出す。 |

**主要処理フロー**:
1. **212行目**: getoptループでオプション(-c, -d, -p, -t, -w)を解析
2. **240-248行目**: コマンドライン引数からユーザーリストを構築（AC_Uフラグ設定）
3. **249-250行目**: -dと-pの排他制御
4. **251行目**: ac()関数呼び出し

#### Step 3: メイン処理ループを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ac.c | `usr.sbin/ac/ac.c` | 402-507行目: ac関数。utmpxレコードを順次読み取り、タイプに応じた処理を行う。 |

**主要処理フロー**:
- **415行目**: setutxdb()でutmpxデータベースをオープン
- **417行目**: getutxent()ループで全レコードを走査
- **442-471行目**: ut_typeに応じたswitch分岐（USER_PROCESS→log_in, DEAD_PROCESS→log_out等）
- **498行目**: 残存セッションに対してlog_out（現在時刻まで）
- **500-506行目**: 出力モードに応じた結果表示

#### Step 4: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ac.c | `usr.sbin/ac/ac.c` | 259-308行目: show, show_users, show_today関数。接続時間を十進時間で表示する。 |

**主要処理フロー**:
- **262行目**: show関数: `(double)secs.tv_sec / 3600`で秒を時間に変換、`%8.2f`で出力
- **268-274行目**: show_users関数: Usersリストを走査して各ユーザーの時間を表示
- **279-308行目**: show_today関数: 日次合計を計算・表示

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

```
main() [204行目]
    |
    +-- add_tty() [100行目] ... -tオプション処理
    +-- update_user() [170行目] ... ユーザーリスト初期化
    +-- ac() [402行目]
           |
           +-- setutxdb() ... utmpxデータベースオープン
           +-- getutxent() ... レコード読み取りループ
           |      |
           |      +-- log_in() [346行目] ... ログイン記録
           |      |      +-- do_tty() [129行目] ... TTYフィルタ判定
           |      +-- log_out() [315行目] ... ログアウト処理
           |      |      +-- update_user() [170行目] ... 時間累計
           |      +-- show_today() [279行目] ... 日次出力(-d時)
           |
           +-- log_out() ... 残存セッション処理
           +-- show_today() / show_users() / show() ... 最終出力
```

### データフロー図

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

utmpxログファイル ──▶ ac(): レコード走査           ──▶ 標準出力
  (UTXDB_LOG)           |                               (テキスト)
                        +-- log_in(): セッション開始記録
                        +-- log_out(): 時間計算・累計
                        +-- update_user(): ユーザー別時間管理
                        +-- show()/show_users()/show_today(): 出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ac.c | `usr.sbin/ac/ac.c` | ソース | メインプログラム（全処理が単一ファイルに集約） |
| Makefile | `usr.sbin/ac/Makefile` | ビルド設定 | ビルド構成（CONSOLE_TTYマクロ定義等） |
