連載
» 2009年02月03日 00時00分 公開

いますぐ使える! BusyBox活用術(6):BusyBoxを拡張してアプレットを追加する方法【前編】 (2/3)

[中村 雄一 busybox同好会,@IT MONOist]

(1)コンパイルメニューへの追加

 「make menuconfig」で表示されるBusyBoxの設定画面のメニューに、アプレットに関する項目を追加します。今回は、「mtd_debug」アプレットに関する項目を追加します。

 メニュー画面の配置などを設定するには、「Config.in」というファイルを使います。「Config.in」は図2のとおり、サブディレクトリにも配置されており、メニュー画面を形成しています。


「Config.in」でメニュー画面の構造が設定されている 図2 「Config.in」でメニュー画面の構造が設定されている

 既存のメニュー項目には、「mtd_debug」を分類すべき場所がありませんので、自分で「MTD utils」というメニューを作成する必要があります。

 まず、アプレットに関するファイルを格納するディレクトリを作ります。今回は、「mtd-utils」コマンドに関するディレクトリなので、「mtd-utils」というディレクトリを作成します。

# mkdir mtd-utils 

 続いて、トップメニューで「MTD utils」を選択したときに表示されるメニュー画面の設定ファイルとして、「mtd-utils/Config.in」の中身を作成しますが、その前にトップディレクトリにある「Config.in」に以下を追加します。

(中略)
source modutils/Config.in
source mtd-utils/Config.in  ←この行を追加
source util-linux/Config.in
(中略) 

 この記述はメニュー表示プログラムに、「mtd-utils/Config.in」の位置を教えるためのものです。

 続いて、「mtd-utils/Config.in」を図3のように作成します。

「mtd-utils/Config.in」の記述 図3 「mtd-utils/Config.in」の記述

 それでは、ここまでの設定内容(図3)と実際に表示されるメニュー画面(図4)(図5)の内容を比較してみましょう。

BusyBoxの設定画面のトップメニュー 図4 BusyBoxの設定画面のトップメニュー
MTD utilsを選択して表示されるメニュー 図5 MTD utilsを選択して表示されるメニュー

 図5で表示される「mtd_debug」を選択することにより、以降のソースコードのコンパイル時に、「config MTD_DEBUG」に対応した定数が定義されるようになります。今回の場合は「CONFIG_MTD_DEBUG」という定数が定義されます。この定数が定義されて「いる」「いない」によって、「mtd_debug」アプレットをコンパイル「する」「しない」を切り替えることができます。

 それでは、以下のコマンドを実行し、ここまでの作業がうまくいっているかどうか(図4、図5と同じ結果になるかどうか)を確認してみましょう。

make menuconfig 

(2)アプレットのひな型の作成

 続いて、必要最低限の機能を持ったアプレットのひな型を作成します。今回は、「hello」と表示するだけの機能を作ります。

 アプレットのひな型を作成するための作業は以下の3つです。

  • (a)アプレットのソースファイルに<アプレット名>_main関数を定義する
  • (b)「include/applets.h」を修正し、<アプレット名>_main関数を登録する
  • (c)「include/usage.h」に、アプレットのヘルプを登録する

 それでは早速、これらの作業に取り掛かりましょう。

(a)アプレットのソースファイルに<アプレット名>_main関数を定義する

 図1で説明したとおり、アプレットの処理の本体は<アプレット名>_main関数です。これをアプレットのソースファイルに定義します。アプレットのソースファイル名は、<アプレット名>.cとするのが慣例です。今回は、「mtd-utils/mtd_debug.c」に以下の定義を行います(リスト1)。

#include "libbb.h"
int mtd_debug_main(int argc, char **argv) {
        printf("hello");
} 
リスト1 「mtd-utils/mtd_debug.c」の定義

 mtd_debug_main関数の処理は、「hello」と表示するだけのシンプルなものです。

(b)「include/applets.h」を修正し、<アプレット名>_main関数を登録する

 mtd_debug_main関数を定義しただけでは、BusyBoxからmtd_debug_main関数は呼ばれません。BusyBoxのデータ構造にmtd_debug_main関数を登録する必要があります。

 mtd_debug_main関数の登録は、「applets.h」のUSE_<アプレット名を大文字にした文字列>が並んだ行に、mtd_debugに関連したエントリ、つまり、USE_MTD_DEBUGエントリを以下のように追加します(リスト2)。

USE_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_MTD_DEBUG(APPLET(mtd_debug, _BB_DIR_SBIN, _BB_SUID_NEVER))  ←この行を追加
USE_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_NEVER)) 
リスト2 「include/applets.h」に追加

 mtd_debugはアプレット名、_BB_DIR_SBINは「/sbin」にアプレットのリンクをインストールする、_BB_SUID_NEVERは「busybox」の実行ファイルのsuidビットを無効にするという意味です(root以外で実行するとsuidビットが0になっていても、rootにならない)。なお、USE_MTD_DEBUGの前後がアルファベット順になるように追加しないと、不具合が発生することがあるので注意が必要です。

 どうしてこの1行を追加することで、mtd_debug_main関数が登録されるのでしょうか?

 「applets.h」をよく眺めてみると、

static struct bb_applet applets[] = { 
USE_エントリの列挙
} 

のようになっていることが分かります。ここでは、appletsという配列の初期化をしています。この配列は、BusyBoxから<アプレット名>_main関数を呼び出す際に使われます。

 そして、USEエントリはマクロであり、先ほど「include/applets.h」に追加した

USE_MTD_DEBUG(APPLET(mtd_debug, _BB_DIR_SBIN, _BB_SUID_NEVER)) 

は、

{mtd_debug_main, 2, 0}, 

のように展開されます。つまり、USE_MTD_DEBUGを追加することで、配列appletsにmtd_debug_main関数が登録されるわけです。

(c)「include/usage.h」に、アプレットのヘルプを登録する

 BusyBoxは、アプレットの起動オプションを間違えたときに表示するヘルプメッセージを登録できます。これは「include/usage.h」に登録します。なお、今回はひな型なので空のメッセージを登録することにします。

 「include/usage.h」の中に以下の行を登録します。

#define mtd_debug_trivial_usage \
        "\n"
#define mtd_debug_full_usage "\n\n" \
        "\n"
#define mtd_example_usage \
        "\n" 

 <アプレット名>_trivial_usageは必要最低限の使い方を、<アプレット名>_full_usageは詳しい使い方を、<アプレット名>_example_usageは利用例を表すメッセージを記述するために使います。

Copyright © ITmedia, Inc. All Rights Reserved.