ゼットログ

よしなしごとを記す

bashのaliasを読む(2)

"$tar Jxf bash-4.1.tar.xz"した後に、bash-4.1配下を見ると、alias.cとalias.hというそのまんまな名前のファイルがあるので、ここから見ていくことにする。alias.hで定義している関数を確認していこう。コメントやソースコードそのものから大まかに何しているか、理解することができた。

initialize_aliases () ハッシュテーブルを作成する
find_alias (name) hash_searchでnameを検索し、データを返す
get_alias_value (name) find_aliasを使って、aliasの値を取り出す
add_alias (name,value) 新しいエイリアスを追加する 上書きにも対応
free_alias_data (data) どこかでエイリアスのデータを解放している
remove_alias (name) 登録しているエイリアスを除外する
delete_all_aliases () 読んで字の如し
all_aliases () エイリアスとして登録されているものを一覧として返す
map_over_aliases (function) all_aliasesに呼び出される。登録しているエイリアスの配列を返す。
skipquotes (string, start) エイリアス定義内容のクォート(”や’)をスキップするための関数
skipws (string, start) エイリアス定義内容の空白をスキップするための関数
rd_token (string, start) 次に出てくるセパレータまで文字列を読み込む。
alias_expand (string) 既出のエイリアス定義よりも長い領域が必要になったときに拡張するために使用する

関数の名前を見るだけでも、やっていることがよく分かる。alias.cとalias.hにはaliasコマンドを実行したときに必要になる各機能が定義されているけれど、aliasコマンドそのものを実行する時のコードが含まれていないことがわかった。
そこで"alias"というキーワードでフォルダ内を検索してみることにした。

$find . -name \* -print -exec grep alias {} \;

すると、alias.c,h以外にもぞろぞろとファイルがヒットした。alias.defというファイルにはaliasコマンドとunaliasコマンドを実行する時に最初に動くように思われる関数が定義されてあった。

alias_builtin (list) aliasコマンド実行時に最初に呼び出される関数。引数をもとに各処理へ振り分けたりする。
unalias_builtin (list) unaliasコマンドを実行時に最初に呼び出される関数。
print_alias (alias, flags)  aliasとしての定義内容を出力してくれる関数

たとえば、以下はalias_builtin関数。all_alias,add_alias,find_aliasなど、alias.cにある関数を呼び出しているのが分かる。しかし、そうなるとalias_builtin関数がどこから呼ばれているのかが気になる。さっきと同じようにalias_builtinというキーワードでgrepをしてみたが、alias.def以外は引っかからなかった・・・だが、それがわかるのもきっと時間の問題だ。7/31までに分からなければ、そのときは勉強会で質問でもしてみよう。

/* Hack the alias command in a Korn shell way. */
int
alias_builtin (list)
     WORD_LIST *list;
{
  int any_failed, offset, pflag, dflags;
  alias_t **alias_list, *t;
  char *name, *value;

  dflags = posixly_correct ? 0 : AL_REUSABLE;
  pflag = 0;
  reset_internal_getopt ();
  while ((offset = internal_getopt (list, "p")) != -1)
    {
      switch (offset)
	{
	case 'p':
	  pflag = 1;
	  dflags |= AL_REUSABLE;
	  break;
	default:
	  builtin_usage ();
	  return (EX_USAGE);
	}
    }

  list = loptend;

  if (list == 0 || pflag)
    {
      if (aliases == 0)
	return (EXECUTION_SUCCESS);

      alias_list = all_aliases ();

      if (alias_list == 0)
	return (EXECUTION_SUCCESS);

      for (offset = 0; alias_list[offset]; offset++)
	print_alias (alias_list[offset], dflags);

      free (alias_list);	/* XXX - Do not free the strings. */

      if (list == 0)
	return (sh_chkwrite (EXECUTION_SUCCESS));
    }

  any_failed = 0;
  while (list)
    {
      name = list->word->word;

      for (offset = 0; name[offset] && name[offset] != '='; offset++)
	;

      if (offset && name[offset] == '=')
	{
	  name[offset] = '\0';
	  value = name + offset + 1;

	  if (legal_alias_name (name, 0) == 0)
	    {
	      builtin_error (_("`%s': invalid alias name"), name);
	      any_failed++;
	    }
	  else
	    add_alias (name, value);
	}
      else
	{
	  t = find_alias (name);
	  if (t)
	    print_alias (t, dflags);
	  else
	    {
	      sh_notfound (name);
	      any_failed++;
	    }
	}
      list = list->next;
    }

  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}

他にも"alias"というキーワードで引っかかったファイルがいくつかあるので列挙。これらも徐々に読み進めていくことにしよう。分かったことは引き続きブログに書いていきます。

aliasというキーワードが含まれているファイル
./builtins/mkbuiltins.c
./execute_cmd.c
./pcomplete.c
./lib/intl/finddomain.c
./lib/intl/localealias.c
./variables.c
./bashline.c
./builtins/alias.def
./builtins/shopt.def

bashソースコードを読む勉強会をやります。

7/31(Sat)の夕方にbashソースコードを読む勉強会をやります。ATNDなどのイベント企画支援ツールには載せていません。興味がある方はz.ohnamiあっとまーくgmail.comまでご連絡ください。人数に若干空きがありますので、ここでひっそりと告知。