2011年4月アーカイブ

自宅のWindowsマシンではMUAはThunerbirdを使っている(最近Becky!から乗り換えた)
会社では、emacsでWanderlustを使っている。
これは、会社のメールはいろいろなところから読むため、sshでログインしてテキスト端末から読みたいから。
で、最近単なるテキストを添付したメールが読めなくて困っている。
具体的には、multipart/mixed なメールで、メール本文は
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
で、添付ファイルはSJISのくせに(Thunderbirdの場合)
Content-Type: text/plain;
 name="hoge.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="hoge.txt"
だったり、(Becky!の場合)
Content-Type: application/octet-stream;
 name="hoge.txt"
Content-Disposition: attachment;
 filename="hoge.txt"
Content-Transfer-Encoding: base64
だったりする。
Wanderlustで見ると、前者は添付ファイル部分が文字化けして見え、後者は添付部分は表示されない。
いずれも、添付部分をeとかvで保存してemacsで開き直せば読める。
この辺は、ちゃんと Content-Type に charset を付けない送信側のメーラが悪いのだと思う(ちなみに、Wanderlustで同じことをやるとSJISなのに charset=US-ASCIIとかつけるらしい)けど、どうせ相手は直してくれないので読む側でなんとかするしかない。
んで、なんとかならないかな~と思ってぐぐって見たけどそれっぽい解を見つけられず、さらにWanderlustとかSEMIとかFLIMはどうも最近開発が停滞してるっぽいことを発見した。(たとえば、EMYを使うと文字化けパートを再変換できそうな記述を見つけたけど、EMYは既に開発されてなさそう)
とりあえず charset がないパートは文字コードを判別して変換してやれば良さそうだと思ってSEMIとかFLIMのソースを読み始めたけれど、emacs lisp がさっぱりわからないのでちっとも進まない。

そこで、Programming in Emacs Lispを見ながらemacs lisp再入門することにした。
読んでいくと、ふんふんなるほど!と思うのだけれど、読み進めていくそばから忘れて行きそうなので、ポイントと言うか、関心したところをメモって行くことにする。

  1. ";"から行末まではコメント
  2. ()で囲んで空白文字で区切った要素を並べたものがリスト
  3. リストをその場で評価したくないときは ' を前置する
  4. 変数の宣言(シンボルへの値のバインド)はset
    (set 'hoge "hoge") ←評価するとシンボルhogeに値"hoge"が入って式の結果は"hoge"
    
  5. setqを使うと、シンボルに前置 ' がいらない上に複数同時に宣言できる
    (setq hoge "hoge")
    (setq moge "moge"
             uha "uha") ←二つ同時に宣言
    
  6. リストを評価すると最初の要素を関数として実行する。リストの残りの要素は引数となる。
    (* 2 3 4) ← 評価すると 24
    (*) ← 評価すると 1
    
  7. 関数の定義は defun を使う。
    (defun hoge (arg1 arg2 arg3) ;← 引数がないときは空リスト()
    "hogeと言う関数の説明. ←説明の1行目は簡潔に
    これは○○する関数なのだよ。"
    (interactive "p") ;←省略可能。interactiveがあるとM-xで呼び出したり、キー割り当てが可能。
    ; "p"は前置引数を取ると言う意味で、他にもいろいろ指定可能
    関数本体
    )
    
  8. letは、perlで言うmyみたいなもん。と思ったけどちょっと違うか。letでバインドした変数は、letの本文の中のみのスコープを持つ。
    (setq hoge "hoge") ; 変数 hoge に値"hoge"をバインド。
    (let ((hoge "moge") moge) (message "hoge=%s moge=%s" hoge moge))
    ; 評価すると、hoge=moge moge=nil とメッセージバッファに表示される。
    hoge ; 評価すると、"hoge" になる。
    
  9. letを使わないで関数内でsetqを使うと外の変数を変えてしまう。
    (defun hoge () (setq hoge "moge"))
    (setq hoge "hoge")
    hoge ; ← 評価すると "hoge"
    (hoge) ; ← 関数 hoge の呼びだしにより、変数 hoge が変化
    hoge ; ← 評価すると "moge"
    
  10. 条件判断は if を使う
    (if 条件式 真のときの動作 偽のときの動作) ; 偽のときの動作は省略可
    
    ※ lispでは、nilのときが偽、それ以外は真。空リスト()とnilは同義。
  11. save-excursion は現在のpoint(カーソル位置)とmark(Ctrl + space)を記録し、抜けるときに戻す。
    (let 変数リスト
      (save-excursion
        本体...)) ; ←みたいな形でセットで使うことが多いらしい。
    
  12. carはリストの最初の要素、cdrはリストの最初の要素を除いた残りの要素のリスト。両方とも非破壊的。
    (setq hoge '(a b c d))
    (car hoge) ; ←評価すると a
    (cdr hoge) ; ←評価すると (b c d)
    
  13. cons はリストの先頭に1要素追加する。
    (cons 'k '(a b c d)) ; ←評価すると (k a b c d)
    
  14. length はリストの長さを返す
    (length '(a b c d)) ; ←評価すると 4
    
  15. nthcdr は最初のn個の要素を除いた残りの要素のリストを返す。非破壊的。
    (nthcdr 2 '(a b c d)) ; ←評価すると (c d)
    
  16. setcarはリストの最初の要素を置き換える。
    (setq hoge '(a b c d))
    (setq moge hoge)
    (setcar hoge 'k) ; ←評価すると k
    hoge ; ← 評価すると (k b c d)
    moge ; ← 評価すると (k b c d)
    
    ※ この結果から、リストを変数にバインドした場合は、ポインタのようなものであることがわかる。
  17. ついでに実験
    (defun hoge (arg0) (setcar arg0 'k))
    (setq hoge '(a b c d))
    (hoge hoge)
    hoge ; ← (k b c d) になるので、関数内で変更される
    
    (defun hoge (arg0) (setq arg0 "changed"))
    (setq hoge "original")
    (hoge hoge)
    hoge ; ← "original" になるので、関数内で変更されない。
    
    ※ この結果から、関数の仮引数はCのポインタやJavaの参照のようなものであることがわかる。仮引数自体は関数ローカルなので、ポイントする先を変更しても呼びだし元に影響しないが、ポイントする先のオブジェクト自体を変更すると呼びだし元に影響する。
  18. setcdr は名前から類推できるので省略。
  19. while
    (while 真偽テスト 本体)
    
  20. インクリメンタ/デクリメンタ
    (setq c 1)
    (setq c (1+ c)) ; c++ (setq c (+ 1 c)) でも同じ
    (setq c (1- c)) ; c-- (setq c (- 1 c)) でも同じ
    
  21. 再帰もできるよ(省略)
  22. cond を使うと if - elseif - elseif - else みたいなのができる
    (cond
      (条件1 結果1)
      (条件2 結果2)
      (条件3 結果3)
    )
    
    ※ 必ず条件と結果をセットにするので、最後を条件なしの else にしたければ必ず真になる条件(tとか1とか)を書けば良い。
    ※ 上から順番に条件が評価され、最初に真になったところの結果だけが評価される。全ての条件が偽になった場合は (cond)の結果はnil。
  23. lambdaは無名関数の定義。defun 関数名の代わりにlambda。
とりあえず、言語仕様についてはこのくらいで。
次のエントリでは、emacs特有の組込関数について見ていきたい。(既にsave-excursionはemacs特有だけど)

@hitoriblog さんから入門書を紹介していただきました。
昨日の続き。
今日は、GNU Emacs Lispリファレンスマニュアルとか、moyashiさんに教えてもらった 優しい Emacs-Lisp 講座 も見ながら補足。
  • setq は変数が既にある場合も上書きするので、宣言だけしたい場合は defvar を使う。(.emacsで上書きするような設定変数などに使う)
    (setq hoge "def")
    (defvar hoge "abc" "hogeの説明") ; 変数hogeを宣言。
    (defvar moge "abc" "mogeの説明") ; 変数mogeを宣言。
    hoge ; 評価すると、def。
    moge ; 評価すると、abc
    
  • carとかcdrとかの操作は、リストに対するものではなくcons cellに対するものだった。cons cellはcarとcdrの二つの要素へのポインタを持つデータ構造のこと。リストは、入れ子になったcons cellのこと。
    '(a . b) ; car が a、cdr が bのcons cell
    '(a . (b . (c . nil))) ; (a b c) と同じ意味。
    
  • 連想リストは、cons cellのリスト
    (setq hoge-alist '((a . b) (c . d) (e . f))) ; 連想リスト
    (assoc 'c hoge-alist) ; 評価すると、(c . d)。cdrを取れば d が得られる。
    (setq hoge-alist '((a b) (c d) (e f))) ; リストも cons cellなのでこれもあり
    (assoc 'c hoge-alist) ; 評価すると、(c d)。cdrを取れば (d) が得られる。
    
  • lispのobjectは、複数の型に所属することができるので、あるobjectの型を一つに限定することはできない。特定の型に所属しているかどうかは調べることができる(instanceofとかtypeofみたいなものか)
    (type-of 1) ; 評価すると integer
    (type-of 1.1) ; 評価すると float
    (type-of "1") ; 評価すると string
    (type-of 'a) ; 評価すると symbol
    (type-of nil) ; 評価すると symbol
    (type-of '()) ; 評価するとsymbol
    (type-of '(a)) ; 評価すると cons
    (type-of [1 2 3]) ; 評価するとvector
    
    (consp ' (a . b)) ; 評価するとt 。cons cellかどうかを調べる。nilはnil。
    (atom 1) ; 評価するとt 。atomかどうかを調べる。cons cellでなければatom。nilだけはatomでありlistである。
    (listp '(a)) ; 評価するとt。cons cell又はnilどうかを調べる。
    (null nil) ; 評価するとt。nilかどうかを調べる。
    (arrayp [1 2 3]) ; 評価するとt。配列かどうかを調べる。
    (arrayp "abc") ; 評価するとt。文字列は文字の配列。
    (sequencep '(a b c)); 評価するとt。シーケンスかどうか調べる。
    (sequencep [1 b "3"]); 評価するとt。配列はシーケンス。
    (sequencep "abc"); 評価するとt。文字列は配列でありシーケンス。
    (symbolp 'a) ; 評価するとt。シンボルかどうかを調べる。
    (vectorp [1 2 3]); 評価するとt。
    (vectorp "abc"); 評価するとnil。文字列は配列だがvectorではない。
    
    emacs固有っぽいbufferとかframeや、char-table, bool-vector等は除いて図にしてみた。
    lispの型
  • 大雑把に言って、変数のscopeには、globalとlocalがあり、さらにバッファローカル、フレームローカルなどのemacs特有のものがある。
    (make-local-variable 'hoge) ; hogeをバッファローカルにする。
    (make-variable-buffer-local 'moge) ; moge を自動的にバッファローカルにするように印を付ける
    
    ※ 正直この部分は理解できていない。
  • hookにはノーマルフックとアブノーマルフックがある。ノーマルフックは、フックに引数も戻り値もない関数又はlambda式を渡すもので、アブノーマルフックは引数または戻り値があるもの。この辺になるとリファレンスマニュアルもだいぶ手抜き感と言うか、説明が足りない感じになってくる。
  • 適当に試したhookのサンプル
    (defun my-hook () "hook用の関数。arg0の4倍をlocal2にセットする"
      (setq local2 (* 4 arg0)))
    
    (defun func1 (arg0) "hook呼びだし関数その1"
      (let (local1 local2)
        (setq local1 (* 2 arg0))
        (setq local2 local1)
        (run-hooks 'func1-hook) ; func1-hookを呼びだし
        local2
        )
    )
    
    (defun func2 (arg0) "hook呼びだし関数その2"
      (let (local1 local2)
        (setq local1 (* 2 arg0))
        (setq local2 local1)
        (run-hooks 'func2-hook) ; func2-hookを呼びだし
        local2
        )
    )
    
    (defun func3 (arg0) "hook呼びだし関数その3"
      (let (local1 local2)
        (setq local1 (* 2 arg0))
        (setq local2 local1)
        (my-hook) ; my-hookを直接呼びだし
        local2
        )
    )
    
    (add-hook 'func1-hook (lambda () (setq local2 (* 3 arg0)))) ; hookにlambda式を追加
    
    (add-hook 'func2-hook 'my-hook) ; hookにmy-hookを追加
    
    (func1 3) ; 9 (lambda式によってarg0の3倍が結果になる)
    (func2 3) ; 12 (my-hookによってarg0の4倍が結果になる)
    (func3 3); 12 (my-hookによってarg0の4倍が結果になる)
    
    (remove-hook 'func2-hook 'my-hook)
    (func2 3) ; 6 (hookが呼ばれないのでarg0の2倍が結果になる)
    
なんでhookのところでこんなややこしいことをやったかと言うと、semi-1.14.6 の mime-display-text/plain と言う関数を読んでいて、(run-hooks 'mime-text-decode-hook) と言う場所があり、mime-text-decode-hookでぐぐったところ、2002 年 9月のよしだむメモと言うページがひっかかり、そこに載っていたhookで mime-display-text/plain の引数にアクセスしていたからです。
私が今まで使ってきた言語は、みんな lexical scope を持っていたので、emacs lisp のような dynamic scope が理解できていなかったのでした。
上記挙動を見てから、再度リファレンスマニュアルの10.9 変数束縛のスコープルール を読み直して、やっと意味が理解できたのでした。
誤解を恐れずに言えば、呼びだし元の変数が呼びだし先から見えると言うことですね。
だからノーマルフックとか言って、パラメータも戻り値もないhookが有り得るのかも知れません。
逆に言うと、hookは注意深く書かないと呼びだし元を簡単に破壊できてしまうと言うことになるのかな。

なんか予定と違って今回もemacs lispの言語仕様っぽい部分を進めましたが、次回はsemiのmime-display-text/plain の中で、パラメータがどうなっているのかを追ってみたいと思います。
うちのTeraStationは TS-1.0TGL/R5 って奴で、2006年に買ったから既に5年目。今までにdiskが1玉死んで交換している。
当時は1Tのdiskは潤沢に見えたけれど、最近では手狭なので増設したいのだが、4玉一気に変えると金銭的に大変なので躊躇している。
TeraStationのFirmWareは購入時のまま1.04。自分でroot奪取して、sshd(ログインするため)とかsnmpd(cactiでディスク使用量とネットワーク負荷をグラフにするため)とかapcupsd(UPSからシャットダウンするため)とかMediaTomb(メディアサーバとして)とか入れてある。これらを入れる過程でgccのセルフコンパイル環境も入っている。
diskが死んだのをきっかけに、いくらRAID5と言ってもdiskが同時に2玉死んだり、RAIDコントローラが死んだらデータを失うので、バックアップを考えることに。
そこで、同じメーカーの LinkStation(LS-CH1.0L) と言うRAIDではないNASを購入して、バックアップ用とした。
TeraStationにはバックアップの機能があるのだが、世代が違うらしくLinkStationにバックアップできない。(今回調べていてわかったのだが、TeraStationのFWをバージョンアップしていればLinkStationにバックアップできたかも知れない)
しょうがないので、TeraStation側でtarとsmbclientを使ってLinkStationにバックアップしていたが、途中で失敗してしまう状態だった。

今回、何が原因でたどり着いたか覚えていないけど、Buffalo Extrasと言うページがあることを知った。
ここの、TeraStation firmware + telnet + root accessと言うリンクに、公式FWをtelnetdを有効にしてroot奪取できるようにしたFWが置いてあり、OpenTera updatesと言うリンクにいくつかのアップデートモジュールが置いてある。
TeraStationのsambaは2.0系だけど、OpenTera updatesには3.0系があるので、こいつを入れるとMacとの相性も良くなるかも知れない(あ、届いたら別記事にするけど私もマカーになりました)

と、言うわけでFWのページからうちのTS-TGL用の1.12のファームウェア(terapro_112e.zip)と、OpenTera updatesのページから以下の3つをダウンロードしてみた。
  • MakeSpace script (MakeSpace_v6.zip)
  • OpenTera Update v5 (OpenTera_v5.zip)
  • Samba 3(No AD support) (samba-3.0.37_ppc.zip)
OpenTera Updates v5の中には、busyboxとかrsyncとか含まれている。
TeraStationの / パーティションは371Mしかなくて、最初から100Mくらい使っているので空きは250M程度。
これだと、gccのツールチェインとかを入れるのは厳しいので、別の手段が必要になる。
私の場合は、/mnt/array1 (NASのデータパーティション)に /opt と言うディレクトリを作成し、/ にシンボリックリンクを張って、アプリをインストールするときに PREFIX=/opt とかしていた。
OpenTeraでは、MakeSpace scriptを使って、/mnt/array1/share (NASのデータパーティションの公開ディレクトリ?)に _local と言うディレクトリを作成し、/opt, /www, /usr/local/* を逃がしているようだ。
私の場合は、/usr/include, /usr/libexec, /usr/src あたりも逃がしていたようだ。(記憶にないけど)
後は、sambaの設定とかもいろいろ変えていた気がするので、FWをアップデートする前にその辺もバックアップしておく必要がある。

準備ができたら、terapro_112e.zip を展開してできた NASUpdater_Japanese.exe を実行する。勝手にTeraStationを見つけてくれるので、どきどきしながらアップデートを実行する。
でかけてしまったので所要時間はわからないけれど、帰って来たら無事にアップデートは終了していた。
アクセスしてみると、共有ディレクトリの内容は特に消えていないようで、無事に成功したようだ。
設定画面を開いてみると、ちゃんと1.12になっている。さっそく、LinkStationへのバックアップをしてみようと思ってバックアップの画面を開くが、バックアップ先にLinkStationが表示されない。
落ち着いてヘルプを読んで見ると、バックアップ検索用パスワードと言うのを設定する必要があるらしいので、LinkStationの設定画面を開いて、共有フォルダの設定でバックアップ用パスワードを設定する。
TeraStationに戻ってパスワードを入力して検索すると、今度はバックアップ先にLinkStationが出て来た。
バックアップには種類があって、「通常」だと単なるフルバックアップ、「上書完全」だと上書き、「上書」だとサイズかタイムスタンプに変化があるときのみ、そして、上書には増分と差分があり、バックアップもとで消去したファイルを消すかどうかが変わる。
私の用途は、ほぼ同サイズのディスクのバックアップなので、「上書(差分)」を選んだ。バックアップの設定では、「バックアップ元が識別可能なフォルダを作成する」と言うのが上記バックアップの種類と並んでバックアップの挙動を決める重要な設定なのだが、これは「しない」を選んだ。
バックアップのスケジュールは、「すぐ」、「毎日」、「毎週」が選べるのだが、LinkStationは普段は起動していないので、「すぐ」にして気が向いたときに手動でやることにする。(LinkStationにはタイマ起動の機能があるので、毎週とかにスケジュールしても良いのだが)
バックアップを開始したら、しばらく時間がかかりそうなので、TeraStationにtelnetしてみる。
まずは、以前と同じく admin ユーザでログインしてみるが、sudo su - でrootになれない。FWアップで/etc/sudoersが上書きされたためだろう。
そこで、今度はmyrootでログインしてみると、初回はパスワードなしでroot権限のユーザでログインできた。
passwdコマンドでパスワードを付けて、topを実行してみると、rsyncが動いている。
TeraStationのバックアップはrsyncらしい。妥当だと思うと同時に拍子抜けする。
とりあえず、バックアップ中はライブラリのアップデートは危険なので、バックアップが終わってからOpenTera updateをあてることにしよう。
と、言うわけでOpenTeraの適用ですが、先に結論を言うと、日本語のファイル名を使っている人は OpenTera を宛てるべきではありません
とりあえずやったことと起きたことを書きます。
  1. MakeSpace_v6.zipを展開して、MakeSpace_v6.sh を実行。
  2. OpenTera_v5.zip を展開して、Update_OpenTera.sh を実行。
  3. samba-3.0.37_ppc.zipを展開して、Update_samba.sh を実行。
  4. 共有フォルダにアクセスできなくなったので、一度再起動。
すると、以下のことが起きました。
  • Windowsから共有フォルダにアクセスすると、日本語ファイル名が文字化け
  • バックアップを実行すると、バックアップ先の日本語ファイル名が文字化け
sambaのログを見ると、UTF-16LEからsjisに変換できません的なエラーが出ています。
OpenTeraがアップデートするライブラリには libiconv が含まれていますが、sambaやrsyncは libiconv をリンクせずに glibc に含まれる iconv 関数を呼んでいるのではないかと推測されます。

OpenTeraのアップデータは、元のファイルをバックアップせずに消してしまうので、元に戻すには再度FWを更新するしかありません。
この工程で、何故か2回ほど失敗しましたが、3回目で無事に OpenTera の root 奪取状態までは復元できました。

とりあえず、以前自分でコンパイルしたsnmpdを動くようにリンクを貼ったりして、当面はこれで運用することにします。

そうそう、新しいFWだとLinkStationにバックアップできるのですが、必ず失敗します。
rsync error: some files could not be transferred (code 23) at main.c(918) [sender=2.6.8]
このエラーメッセージで検索すると、Q&A バックアップログの読み方と対策にたどり着きました。
code 23と言うのは、TeraStationの使用禁止文字を使ったファイル名があると言うものらしいです。
rsyncで文字化けディレクトリがバックアップ先にできて、消せなくなったせいかな~とも思いますが、OpenTeraを入れる前から出ているような気もするので正確なところは不明です。

また、今回バックアップしていて気がついたのですが、動画のようなファイルサイズが大きくて圧縮が効かないファイルが大量にある場合は、TeraStationのバックアップの設定で圧縮を有効にしてはいけません。
圧縮なしの場合はだいたい 8~9MByte/secで転送されるのですが、圧縮ありにすると1MByte/sec以下にまで転送速度が落ち込んでしまいます。
最近のCPUだと圧縮コストはほとんど気になりませんが、NASのCPUだとまだまだ厳しいようです。
Macが届いたのでTeraStationにアクセスしたところ、見事に日本語が化けている。FreeBSDのsamba3にアクセスすると化けないので、TeraStationのsamba2とMacの文字コード問題なんだろう。
OpenTeraのsambaはiconv周りの問題で使えないので、自分でsambaをビルドすることにする。
参考にしたのは2010/02/03:TerastationPROのLinuxBox化(下)。先にここを見ておけば文字化けでreflashすることもなかったんだけどね。
私の場合、以前root奪取してgccとか入れてあったので、使えるものは使う方向で行く。(一からやった方が他の人の参考になるんだろうけど、TeraStationのスペック的にコンパイル時間がかかるので)
と言う訳で現在のTeraStationがどう言う状態になっているかと言うと、以下のような感じ。
  • OpenTeraは適用していない
  • ln -s /mnt/array1/opt /opt してある。/mnt/array1/opt は以前Vineのrpmから入れたり、ビルドしたりしたもの。
  • /optに何を入れたかはほとんど覚えていない。
  • とりあえず、/opt/bin:/opt/usr/bin:/opt/usr/local/bin/ にPATHを通すscriptを書いて、sambaビルド時には実行しておく。(rootの.bashrcとかには怖くて入れない)
  • 上記スクリプトで、/opt/usr/lib:/opt/usr/local/libにLD_LIBRARY_PATHを通しておく。(私の環境だと、/opt/lib/libc.soにLD_LIBRARY_PATHを通してしまうと、何もできなくなってしまう)

まずは、sambaのソースを持ってくる。現在の安定板の最新と言うことで samba-3.5.8。(ちなみに、FreeBSDには3.5.6が入っていた)
展開すると、トップにはconfigureとか存在しない。3.0くらいまでは source ってディレクトリがあったけど、何故かsource3とsource4と言うディレクトリがあり、howto4.txtとか言うファイルもあって、「あれ?間違えて samba4 持ってきた?」とか思うが、どうみても3.5.8である。
とりあえず、source3でconfigureを実行してみると、エラーが出るのでいろいろ手を打つ。(元の状態(optに何が入っているか)がわからないので、ちっとも参考にならないと思うけど)
  • まずは、/usr/lib/libc_nonshared.a がないと言って ld がエラーになるので、ln -s /opt/usr/lib/libc_nonshared.a /usr/lib する。
  • 次に、stdio.h がないと言って cpp がエラーになるので、 ln -s /opt/usr/include /usr/include する。
  • 次に、linux/limits.h がないと言って(略)、ln -s /opt/usr/src /usr/src する。
これで、オプションなしのconfigureは通るようになったので、TeraStationのconfigureオプションを考える。
./configure --prefix=/opt/usr/local/samba \ 
   --with-piddir=/var/run \ 
   --with-libiconv=/opt/usr/local
参考にしたサイトと違うのは、prefixと、libiconvの場所。krb5とadsはいらないと思ったので外した。configdirは$PREFIX/etcで良いので指定しない。
途中、headの-lオプションがないとか、dirnameがないとか言ってるが、一応最後までconfigureが実行されて、Makefile-noincludesと言うファイルができる。試しに make -f Makefile-noincludesってやるとビルドが始まったけど、やっぱり dirname がないとか言ってる。
そこで、busyboxにheadとdirnameを追加してリビルド。
しかし、headには-lオプションなんてない。FreeBSDのmanで見てもないので、何かエラーメッセージを読み間違えたか?
dirnameが使えるようにして再度 configureを実行したところ、Makefileができたのでmakeする。
すると、libnetapi.soをビルドするところで __dn_expand が見つからないとか言ってコンパイルエラーになる。
昔sshdをビルドしようとしてはまったときとまったく同じ状況だったので、MakefileのLIBSの行に /lib/libresolv.so.2を追加。
今度は、 /usr/lib/libpthread_nonshared.a がないと言われるので、 ln -s /opt/usr/lib/libpthread_nonshared.a /usr/lib/ で無理矢理回避。
ここまでやってやっとバイナリができたので、make install。
/etc/init.d/smb stop でオリジナルのsamba2を止めて、前回失敗したOpenTeraが作成したsmb.conf を /opt/usr/local/samba/lib にコピーしてみる。
試しに、/opt/usr/local/samba/sbin/smbd -D で起動してみると、libwbclient.so が見つからないと言って起動しないので、LD_LIBRARY_PATH=/opt/usr/local/samba/lib をつけて起動する。
すぐに死んでしまうので、/opt/usr/local/samba/var/log.smbd を確認すると、
smbd/server.c:659(open_sockets_smbd)
  open_sockets_smbd: No sockets available to bind to.
と言うエラーが出てうまく動かない。
smb.conf に interfaces = lo eth0 とか足してもダメなので、libc周りがおかしいせいなんじゃないかと思う。
この辺でお手上げなので、おかしい環境で続けるのはやめて、一度昔入れた /opt は捨てて、冒頭に挙げた参考URLの通りにやってみることにする。
と、言うわけで続く。
再度2010/02/03:TerastationPROのLinuxBox化(下)を見ながらリベンジ。
今までは、FreeBSDでrpm2cpio | cpio -id していたのだが、効率を上げるために記事の通りTeraStationにrpm2cpioとcpioを入れる。
続いて、開発環境関連のrpmをftp.jaist.ac.jpから持ってくる。
持ってきたのは、参考サイトに書いてある以下のもの。
  • autoconf-2.59-2vl3.noarch.rpm
  • automake-1.8.5-0vl1.noarch.rpm
  • binutils-2.14.90.0.7-1vl2.ppc.rpm
  • diffutils-2.8.1-11vl1.ppc.rpm
  • ftp-0.17-15vl2.ppc.rpm
  • gcc-3.3.2-0vl8.ppc.rpm
  • gcc-c++-3.3.2-0vl8.ppc.rpm
  • gcc-cpp-3.3.2-0vl8.ppc.rpm
  • glibc-common-2.3.3-3vl1.ppc.rpm
  • glibc-devel-2.3.3-3vl1.ppc.rpm
  • initscripts-6.51-1vl26.ppc.rpm
  • kernel-headers-2.4.26-0vl17.ppc.rpm
  • less-358-0vl9.ppc.rpm
  • make-3.80-0vl3.ppc.rpm
  • ntp-4.2.0-0vl3.ppc.rpm
  • pkgconfig-0.15.0-0vl2.ppc.rpm
  • popt-1.6.5-1vl8.ppc.rpm
  • sh-utils-2.0.11-9vl6.ppc.rpm
  • textutils-2.0.17-0vl4.ppc.rpm
  • unzip-5.50-5vl2.ppc.rpm
  • vim-6.3.31-0vl1.ppc.rpm
  • こいつらを、参考サイトに従って /mnt/array1/newroot に展開。(参考サイトだと /mnt/disk1だが、RAIDを組んでいると /mnt/array1なので読み替えが必要。そのことも参考サイトには書いてあるけど)
    展開したら、参考サイトにあるスクリプトで既存の / と比較する。
    ./usr/bin/getent
    ./usr/bin/locale
    ./usr/bin/env
    ./usr/bin/expr
    ./usr/bin/id
    ./usr/bin/tty
    ./usr/bin/head
    ./usr/bin/sum
    ./usr/bin/tail
    ./usr/bin/tr
    ./usr/bin/wc
    ./usr/share/locale/locale.alias
    ./usr/share/zoneinfo/America/Buenos_Aires
    ./usr/share/zoneinfo/America/St_Johns
    ./usr/share/zoneinfo/America/Santiago
    ./usr/share/zoneinfo/America/Anchorage
    ./usr/share/zoneinfo/Asia/Baghdad
    ./usr/share/zoneinfo/Asia/Bangkok
    ./usr/share/zoneinfo/Asia/Calcutta
    ./usr/share/zoneinfo/Asia/Dubai
    ./usr/share/zoneinfo/Asia/Kabul
    ./usr/share/zoneinfo/Asia/Katmandu
    ./usr/share/zoneinfo/Asia/Kuwait
    ./usr/share/zoneinfo/Asia/Rangoon
    ./usr/share/zoneinfo/Asia/Tokyo
    ./usr/share/zoneinfo/Asia/Tehran
    ./usr/share/zoneinfo/Asia/Taipei
    ./usr/share/zoneinfo/Asia/Dhaka
    ./usr/share/zoneinfo/Atlantic/Cape_Verde
    ./usr/share/zoneinfo/Australia/North
    ./usr/share/zoneinfo/Australia/Adelaide
    ./usr/share/zoneinfo/Europe/Athens
    ./usr/share/zoneinfo/Europe/Rome
    ./usr/share/zoneinfo/Europe/London
    ./usr/share/zoneinfo/Indian/Maldives
    ./usr/share/zoneinfo/Pacific/Guam
    ./usr/share/zoneinfo/Pacific/Marquesas
    ./usr/share/zoneinfo/Pacific/Midway
    ./usr/share/zoneinfo/Pacific/Ponape
    ./usr/share/zoneinfo/Pacific/Tongatapu
    ./usr/share/zoneinfo/Pacific/Auckland
    ./usr/share/zoneinfo/Pacific/Honolulu
    ./usr/share/zoneinfo/zone.tab
    ./usr/share/zoneinfo/UTC
    ./usr/share/zoneinfo/MST
    ./usr/share/zoneinfo/EST5EDT
    ./usr/share/zoneinfo/PST8PDT
    ./usr/share/zoneinfo/EST
    ./usr/share/zoneinfo/MST7MDT
    ./usr/share/zoneinfo/CST6CDT
    ./usr/lib/libpopt.so.0.0.0
    ./usr/sbin/ntpdate
    ./bin/usleep
    ./bin/date
    ./bin/echo
    ./bin/false
    ./bin/sleep
    ./bin/stty
    ./bin/su
    ./bin/true
    ./bin/uname
    ./bin/cat
    ./etc/inittab
    ./etc/rc.d/init.d/halt
    ./etc/sysctl.conf
    ./etc/pam.d/su
    ./sbin/ifdown
    ./sbin/ifup
    
    ...だいぶ参考サイトよりも多い。
    被ったものはリネームとあるので、泣きながらnewrootの方をリネームしていく。
    手でやるとミスるので、スクリプトが吐いた newfile.dup をエディタで修正しよう。さらに、/usr/share/zoneinfo/* はファイルを一つ一つリネームするのもなんなので、ディレクトリ毎リネームする。(たぶんなくても困らないでしょ?)
    #!/bin/bash
    cd newroot
    
    files=`cat << EOT
    ./usr/bin/getent
    ./usr/bin/locale
    ./usr/bin/env
    ./usr/bin/expr
    ./usr/bin/id
    ./usr/bin/tty
    ./usr/bin/head
    ./usr/bin/sum
    ./usr/bin/tail
    ./usr/bin/tr
    ./usr/bin/wc
    ./usr/share/locale/locale.alias
    ./usr/share/zoneinfo
    ./usr/lib/libpopt.so.0.0.0
    ./usr/sbin/ntpdate
    ./bin/usleep
    ./bin/date
    ./bin/echo
    ./bin/false
    ./bin/sleep
    ./bin/stty
    ./bin/su
    ./bin/true
    ./bin/uname
    ./bin/cat
    ./etc/inittab
    ./etc/rc.d/init.d/halt
    ./etc/sysctl.conf
    ./etc/pam.d/su
    ./sbin/ifdown
    ./sbin/ifup
    EOT
    `
    for i in $files
    do
    echo $i
    mv $i $i.vine
    done
    
    こいつを /mnt/array1 (newrootがあるディレクトリ) で実行する。
    続いて、リンクを張る。参考URLと同じ手順でやったら、
    • mv usr/src/linux-2.4.26/include/* usr/include/ の手順で net と scsi が usr/include に既にあるので mv に失敗する。
    • usr/include で asm → asm-ppc のリンクは既にある
    と言う状態だった。
    この状態で、再度rootと比較するスクリプトを動かして、出力が空であることを確認しておくと、後で既存のファイルを上書きしてしまうことがない。
    この時点で、newrootの du -ah の結果は 147M、df -ha での / の空きは 294M。参考サイトのように / は拡張していないが、入れても深刻なことにはならないだろうと判断して、展開していくことにする。
    # cd /mnt/array1/newroot
    # tar zcvf ../TeraLinuxKit.tar.gz bin/ etc/ usr/
    # tar zxvfk /mnt/disk1/TeraLinuxKit.tar.gz -C /
    

    続いて、sambaの依存ツール/ライブラリのビルド。
    参考サイトと現時点でバージョンが違うので、一応リストアップ。 Berkeley DB(今は Oracleなのね)、openldap、krbはいらないと思ったので入れない。
    上記をひと通りダウンロードして、m4からスタート。
    しかし、2番目のautoconf の時点で perl の Data/Dumper.pmがないと言うエラーで止まる。
    面倒臭くなったので、既に入っているツール類は新しくしなくても良いや〜とlibiconvのコンパイル。
    と思ったらpatchをあてるのにGNU patchが必要だったのでこちらを先にインストール。
    libiconvは無事に入ったので、続いて samba の configure。
    # ./configure --prefix=/opt/samba --with-piddir=/var/run --with-libiconv=/usr/local
    
    としてみたら、またまたMakefile-noincludesができて Makefileができない。
    configureの出力を見ていると、egrepがないとか言ってる。
    またbusyboxにしても良かったんだけど、今回はGNU grep(grep-2.7.tar.gzを持ってくることに。
    libiconvが先に入っていると、オプション無しのconfigureでは libiconv をリンクしてくれないので、以下のオプションでやってみた。
    # ./configure --with-libiconv-prefix=/usr/local
    
    ら失敗するので
    # ./configure --without-libiconv-prefix
    
    にしても駄目なので、大人しくbusyboxを使う。
    しかし、やはり Makefile-noincludes しかできない。
    だいぶくじけてきたので、make -f Make-noincludes でビルドしてみることに。
    何事もなかったかのようにビルドは成功したので、make -f Makefile-noincludes install でインストール。
    smb.conf と lmhosts を/opt/samba/lib にコピーして、smbdを起動しようとすると、libwbclient.so.0が見つからない。
    LD_LIBRARY_PATH=/opt/samba/lib で smbd を起動すると、No sockets available to bind to.で落ちる。 ...昨日とまったく一緒です。本当にありがとうございました。
    config.logを再度見てみると、ipv6関連のテストがyesになっています。
    TeraStationはipv6に対応してないし、libipv6なんて見当たらないのですが、なんでこうなるのか謎です。

    何が悪いのか検討もつかなかったので、試しに参考サイトがいれているsamba3.0系の最新版であるsamba-3.0.36で試してみることにしました。
    とりあえず、3.5でlibwbclient.so.0が見つからないのは、ビルド時にリンカに-Rオプションが渡っていないからだと思うので、参考サイトと同じように configure実行時にLDFLAGSを追加。
    #  CPPFLAGS="-I/usr/local/include" LDFLAGS="-R/usr/local/lib -L/usr/local/lib" \
    ./configure --prefix=/opt/samba --with-piddir=/var/run --with-libiconv=/usr/local
    
    これで、無事にconfigureが終了してMakefileができたので、make, make installであっけなくインストール完了。
    起動してみたら、WindowsからもMacからも日本語のファイル名が文字化けせずに動作するようになりました。
    Macがアクセスすると、各ディレクトリに .DS_Store と言うファイルができてしまうので、Windowsから見るときに気になりそうですが。
    あとは、/etc/init.d/smb ファイルをいじって、/opt/samba のファイルを起動するように直すだけ。
    OpenTeraのsambaをいれている場合は、/etc/init.d/smbの冒頭で定義しているSAMBA3を変えればそのままいけそう。
    私の場合は、OpenTeraのsamba3は適用しなかったので、zipの中身を以下のように配置した。
    • /etc/samba/smb.conf ← TeraStationの管理ファイルが生成する samba2用の設定ファイル
    • /etc/samba/lmhosts ←同上
    • /etc/samba/smb2smb3.pl ← OpenTeraのsamba3から持ってきて、日本語対応に書き換えた物
    • /etc/init.d/smb ← OpenTeraのsamba3から持ってきて、SAMBA3を /opt/samba に書き換えた物
    • /opt/samba/lib/smb.conf ← smb2smb3.pl が変換したsamba3用の設定ファイル。
    • /opt/samba/lib/lmhosts ← /etc/init.d/smb がコピーした samba3用の設定ファイル。
    • と、言うわけで smb2smb3.pl の書き換え。
      *** smb2smb3.pl.orig    Sat Apr 30 07:49:06 2011
      --- smb2smb3.pl Sat Apr 30 07:53:15 2011
      ***************
      *** 50,58 ****
          close(SMB2_CONF);
          
        # Open up the Samba 3 output file
      !   if (!open (SMB3_CONF, ">/usr/local/samba3/lib/smb.conf")) 
          { 
      !       die "File Open Error - /usr/local/samba3/lib/smb.conf\n"; 
          }
        
        
      --- 50,58 ----
          close(SMB2_CONF);
          
        # Open up the Samba 3 output file
      !   if (!open (SMB3_CONF, ">/opt/samba/lib/smb.conf")) 
          { 
      !       die "File Open Error - /opt/samba/lib/smb.conf\n"; 
          }
        
        
      ***************
      *** 119,124 ****
      --- 119,132 ----
              {
                      # Remove line - this is not used by Samba 3
              }
      +       elsif ($line =~ m/coding system/)
      +       {
      +               print SMB3_CONF "    display charset = CP932\n";
      +               print SMB3_CONF "    dos charset = CP932\n";
      +               print SMB3_CONF "    unix charset = CP932\n";
      +               print SMB3_CONF "    load printers = no\n";
      +               print SMB3_CONF "    disable spoolss = yes\n";
      +       }
              elsif ($line =~ m/printer admin/)
              {
                      # Remove line - this is deprecated by Samba 3
      
      参考サイトと違うのは、sambaのインストール先と、dos charset。既存のファイル名がsjisなので。

      ふ〜、これでやっとMacの設定を始められる。
VAIOの調子がだいぶ悪いので、そろそろ新しいノートが欲しいな〜とか考える。
しかし、いい加減Windows PCも飽きてきたので、Macの購入を考える。
MacBook Airが魅力的だったんだけど、メインマシンのリプレースとしてはCPUが非力(今と一緒だけど)だったので、MacBook Proにすることに。
Apple Storeのカスタマイズで、15インチ MacBook Proを以下のようにした。(しかし、appleのページは現行機種しか表示しないので、記録としてこの機種買ったよ、と言うのが残しにくいね。)
  • 2.0GHzクアッドコアIntel Core i7
  • 4GB 1333MHz DDR3 SDRAM - 2x2GB
  • 256GBソリッドステートドライブ
  • 8倍速SuperDrive (DVD±R DL/DVD±RW/CD-RW)
  • MacBook Pro 15インチ高解像度光沢ワイドスクリーンディスプレイ
  • バックライトキーボード (JIS) + 製品マニュアル
デフォルトから変えたのは、HDDをSSDにしたのと、液晶を高解像度版にしたくらい。
本当はメモリ8Gにしたいとか、CPUももっと良いのをとか思ったんだけど、予算的に無理すぎた。
そして、Windowsでしか動かないゲームも動かしたかったので、Boot Camp用に Windows 7 DSP版を購入。

4/21に注文して、4/28日に届いた。
箱を開けてみると、重い、でかい!
買う前に重さだけは調べて、今のVAIOと同じくらい。大きさは15インチにしたから、これも同じくらいと考えていたんだけど、明らかに横幅が大きい。
厚さは少しmacの方が小さいか。
まずは無線LANの設定をする。初期セットアップの過程でやるんだけど、この時点でMACアドレスがわからないので、無線LANのMACアドレスフィルタリングに登録できなくてちょっと困る。
とりあえず、無線LANのアクセスポイントの履歴から、許可してみたらつながった。
適当に初期セットアップを終わらせたら、Boot Campを起動。80GをWindows用に確保して、Windows7をインストール。
Windows7のインストーラで、パーティションのフォーマットが直感的にわからないところにあるのがはまりポイントか。
やりたかったゲームが起動することを確認したので、MacOSに戻る。
最初にやったのは、トラックパッドの設定。「タップでクリック」にチェックを入れる。
続いて、Firefox, Thunderbird, KeePassX, Skype, Dropboxなど思いつくままにインストール。
FirefoxとThunderbirdは、WindowsのProfilesディレクトリの中身をコピーしてきて、profiles.iniを書き換えてそのまま環境移行。
実は、メールの方はMail.appを試してみたんだけど、自宅のIMAPサーバに繋がったものの、送信済みのフォルダの名前が設定できなくて、Sent Messages固定みたいなので、速攻で捨てて Thunderbirdにした。

別記事で書いたけど、やっとiTunesの音源を置いているNASがMacからもアクセスできるようになったので、いよいよiTunesの移行。
もともとWindows(Vista)では、NASのL:¥music が iTunesの「[iTunes Media]フォルダーの場所」として設定してあって、iTunesのディレクトリは C:\Users\ユーザ名\Music\iTunes にあったので、iTunesディレクトリをまるごとコピーしてきた。
Macの方では、~/Music/iTunes が該当するので、一度iTunesを起動して規約に同意した後、WindowsのiTunesディレクトリを上書きでコピーする。
iTunesディレクトリのうち、iTunes Library.itl がライブラリのデータで、iTunes Music Library.xml が音楽ライブラリのデータ?
とりあえず、itlの方はバイナリでいじれないので、iTunes Music Library.xml をエディタで編集して、L: を /Volume/disk に置換してみる。(/Volume/disk はNASをマウントしたディレクトリ。結果として、file//localhost/Volume/disk とかなるんだけど、本来は file://NASのホスト名/disk とかの方が正しいんじゃないかなあ。)
そして、optionを押しながらiTunesを起動し、iTunes Library.itlを選択する。
最初、コピーしたんだから良いだろうと思って option を押しながら起動しなくてやって、ライブラリが壊れてしまって非常にはまった。
この状態でiPhoneをつなぐと、iPhone内にある購入したアプリを転送するかどうか聞かれたので、転送を選ぶと、ライブラリを転送したおかげか、新しいiPhoneとか別のマシンで同期したとか言われることもなく、普通に同期ができた。
後やったのは、sambaをビルドしているあいだ暇だったので、twitterクライアントとして夜フクロウをインストールしたり、Growlをインストールしたり、VMware Fusion3の体験版を入れて Boot CampのWindowsを起動したりした。
いろいろ入れるために、MacPortsを導入することにする。
InstallingMacPorts - MacPortsを見ながら作業する。
  1. Xcodeのインストール。
    MacBook Proに付属の2枚のDVDのうち、Applications Install DVD ではなく OS X Install DVD の方を入れると、Xcode.mpkg と言うのが入っているので、ダブルクリックするとインストーラが起動する。(インストールしてからXcodeを起動してみたら、3.2.3だった。
  2. 環境変数の準備
    ~/.profileを作成し、以下の内容を書く。
    export PATH=/opt/local/bin:/opt/local/sbin:$PATH
    
  3. Snow Leopard用のdmgをダウンロードしてきてインストールする。
え〜っと、これでportコマンドが使えるようになります...って、記事にするほどの内容じゃないなあ。

じゃあ、emacsのインストールと合わせ技にしよう。
Macのemacsには、carbonベースのemacs22と、cocoaベースのemacs23があるとか、IMEパッチをあてないといけないとか、いろいろ面倒そう...。
え〜っと、以下で終了。
$ sudo port install emacs-app-devel

もう、簡単過ぎて何も書くことがないですね。
ちなみに、emacsが入ったので何か見てみようと思って ~/.profileを見たら、macportsのインストーラがしっかりPATHを書きこんでいた。
インストーラを使う限り、準備はXcodeを入れておくことくらいみたい。

後は、会社の設定持ってきて anything.el とか使えるようにするか。

追記。
ターミナルからemacsと打つと、Xcodeに入っているemacs22が emacs -nw状態で起動する。
じゃあ、portで入れたemacsをターミナルから起動するにはどうするかと言うと、open -a emacs でいけるらしい。
open -a emacs ファイル名だと、emacsが起動して別ウィンドウでファイルを開く。
emacsは起動しっぱなしにして、M-x server-start して、emacsclientから繋いだら良いと思ったのだが、PATHが通っている /usr/bin/emacsclientだと駄目だった。
/Applications/MacPorts/Emacs.app/Contents/MacOS/bin/emacsclient を使うと繋がる。
ここにPATHを通すのもどうかと思ったので、上記emacsclientを/opt/local/bin/ にリンク張ってやると、emacsclient で起動中のEmacs.appに接続できる。

vimperatorのpluginをgitで持ってきたくて、sudo port install GitXしてみる。
今回もすんなり行くと思ったら、db46のビルドで失敗する。
ログを見ると、
 /usr/bin/gcc-4.2 -c -I. -I../dist/.. -I/opt/local/include -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -pipe -O2 -arch x86_64 -fno-strict-aliasing ../dist/../libdb_java/db_java_wrap.c  -fno-common -DPIC -o .libs/db_java_wrap.o
../dist/../libdb_java/db_java_wrap.c:123:17: error: jni.h: No such file or directory
みたいな感じ。
/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers を見ると、ちゃんとjni.hはある。
ある?よくよくみると、jni.h はファイルではなくディレクトリになっている。これでは読めるはずがない。
ファイルの更新時間的に、Xcodeを入れたときにおかしくなったらしい。
こんなところ見てないから、最初からおかしかったのか、Xcodeがおかしいものを入れたのか、Xcodeが壊したのかはわからない。
とりあえずソフトウェア・アップデートでXcodeを3.2.3から3.2.6に上げてみたが改善せず。
$ sudo /Developer/Library/uninstall-devtools --mode=all
でXcodeをアンインストールしてみても変わらない。
developer.apple.comからxcode_3.2.6_and_ios_sdk_4.3.dmgをインストールしてみたら...治った!
これで、無事にgitが使えるようになりました。
やっとgitが動くようになったので、vimperatorの設定。
まずは、dropboxの下にpluginを持ってくる。
$ mkdir ~/Dropbox/vimperator
$ cd ~/Dropbox/vimperator
$ git clone git://github.com/vimpr/vimperator-plugins.git
続いて、pluginの中から plugin_loaderだけ~/.vimperator/pluginに入れる。
$ mkdir ~/.vimperator/plugin
$ ln -s ~/Dropbox/vimperator/vimperator-plugins/plugin_loader.js ~/.vimperator/plugin
ついでに、.vimperatorrcもdropboxに実体を置いておく。
$ touch ~/Dropbox/.vimperatorrc
$ ln -s ~/Dropbox/.vimperatorrc ~/
後は、~/.vimperatorrcを編集する。
" 使いたいpluginがあるディレクトリを並べる。
let g:plugin_loader_roots = "~/Dropbox/vimperator/vimperator-plugins/"
" 使いたいpluginを並べる。
let g:plugin_loader_plugins = "_libly,feedSomeKeys_3,statusline-toolbar,ldrize_cooperation,migemo_completion"
" 後は普通に...
2011年4月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

このアーカイブについて

このページには、2011年4月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2010年12月です。

次のアーカイブは2011年5月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 6.1.1