2011/08/12

Mac で Planex URS-03 (USB-Serial 変換アダプタ) を利用する

Planex URS-03 もメイカーは Mac 用のドライバを提供していないが、 利用しているチップセットのメイカー (Prolific Technology Inc. 社) の Web サイト から Mac 用のドライバをダウンロードしてインストールした上で、 ドライバの Info.plist ファイルに URS-03 の Vendor ID と Product ID を登録する事で正しく利用できる様になる。
URS-03 の場合は /dev/tty.usbserial という デバイスとして認識されるので、 このデバイスを利用して通信する事ができる様になる。

URS-03 の Vendor ID と Product ID はアダプタを接続した状態で、 以下のコマンドを実行して PL2303 を検索する事で取得可能である。

# /usr/sbin/ioreg -l | less
	
X code がインストールされている場合は /Developer/Applications/Utilities/USB Prober.app を実行して Conposite device from ATEN International Co. Ltd. を検索すれば、 Device Descriptor セクションから取得可能である。

URS-03 の Vendor ID は 1367(10)、 Product ID は 8200(10) なので、 Info.plist の内容を以下の様に修正する。

  1<?xml version="1.0" encoding="UTF-8"?>
  2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3<plist version="1.0">
  4    <dict>
  5        <key>CFBundleDevelopmentRegion</key>
  6        <string>English</string>
  7        <key>CFBundleExecutable</key>
  8        <string>ProlificUsbSerial</string>
  9        <key>CFBundleGetInfoString</key>
 10        <string>ProlificUsbSerial v2.2.0, Copyright 2006 Prolific Technology Inc.</string>
 11        <key>CFBundleIdentifier</key>
 12        <string>com.prolific.driver.PL2303</string>
 13        <key>CFBundleInfoDictionaryVersion</key>
 14        <string>6.0</string>
 15        <key>CFBundleName</key>
 16        <string>Mac OS X Driver for Prolific USB-to-Serial Bridge Device</string>
 17        <key>CFBundlePackageType</key>
 18        <string>KEXT</string>
 19        <key>CFBundleShortVersionString</key>
 20        <string>2.2.0</string>
 21        <key>CFBundleSignature</key>
 22        <string>????</string>
 23        <key>CFBundleVersion</key>
 24        <string>2.0.0</string>
 25        <key>IOKitPersonalities</key>
 26        <dict>
 27                <key>067B_2303</key>
 28                <dict>
 29                        <key>CFBundleIdentifier</key>
 30                        <string>com.prolific.driver.PL2303</string>
 31                        <key>IOClass</key>
 32                        <string>com_prolific_driver_PL2303</string>
 33                        <key>IOProviderClass</key>
 34                        <string>IOUSBInterface</string>
 35                        <key>bConfigurationValue</key>
 36                        <integer>1</integer>
 37                        <key>bInterfaceNumber</key>
 38                        <integer>0</integer>
 39                        <key>idProduct</key>
 40                        <integer>8200</integer>              <!-- 変更 -->
 41                        <key>idVendor</key>
 42                        <integer>1367</integer>              <!-- 変更 -->
 43                </dict>
 44        </dict>
 45        <key>OSBundleLibraries</key>
 46        <dict>
 47                <key>com.apple.iokit.IOSerialFamily</key>
 48                <string>1.0.4</string>
 49                <key>com.apple.iokit.IOUSBFamily</key>
 50                <string>1.8</string>
 51                <key>com.apple.kpi.iokit</key>
 52                <string>10.0.0</string>
 53                <key>com.apple.kpi.libkern</key>
 54                <string>10.0.0</string>
 55                <key>com.apple.kpi.mach</key>
 56                <string>10.0.0</string>
 57        </dict>
 58    </dict>
 59</plist>
    
これで kextload (8) を実行してドライバをロードすると URS-03 が無事に利用可能となる。

ただし、本来サポート対象のものを無理矢理利用しようとしているので、 URS-03 を接続した際にカーネルモジュールを自動でロードできない。 そこで 起動時に任意のコマンドを実行する 機能で起動時にカーネルモジュールをロードする設定を追加すると URS-03 を接続するだけで利用可能になる。

2011/07/07

パイプコマンド中の終了ステータス取得

シェルスクリプトでは頻繁に複数のコマンドをパイプで連結して使用するが、 パイプの途中のコマンドの終了ステータスは通常では参照できない。
そこでリダイレクトを利用してパイプの途中のコマンドの 終了ステータスを取得する方法を考えてみる。

  1exec 3>&1
  2ret1=`{ { command1; echo $? 1>&3; } | command2; } 3>&1`
  3ret2=$?
    
exec を利用してあらかじめ FD3 を利用可能にしておき、 command1 の終了ステータスを FD3 に出力している。
command2 の実行後に FD3 の出力を FD1(標準出力) に変更しているので、 ret1 は標準出力から command1 の終了ステータスが取得できる。 command2 の終了ステータスはそのまま $? を参照して ret2 に格納される。

2011/07/04

awk (1) 小技

先日参加した勉強会で awk (1) 関連の発表があったので、 ちょっとした小技を紹介してみる。

system() を利用する際の注意
awk の中で外部コマンドを実行する場合は 組み込み関数 system() が利用できるが、 この関数を利用して外部コマンドを実行すると 入出力 stream がオープンされるので、 ファイルディスクリプタが消費されてしまう。
従って awk 内で何度も system() を実行すると、 オープンできるディスクリプタの上限を超過してしまい、 awk の実行が中断されてしまう可能性がある。
その場合 close() を利用して system() がオープンした stream を閉じれば良いのだが、 awksystem() では stream を明示的に扱わない。 そこで system() で実行したコマンドを close() の引数で指定する事で stream を閉じる事ができる。
  1awk '{
  2    :
  3    # コマンドを生成
  4    command = sprintf("%s %s %s", command, arg1, arg2);
  5    # コマンドを実行して結果を取得
  6    buf = system(command);
  7    # stream をclose
  8    close(command);
  9    :
 10}'
            
関数内ローカルな変数の使用
nawkfunction を利用する事で 内部関数を作成する事ができるが、 関数内でローカルな変数を明示的に定義する事ができない。 そこで関数宣言の仮引数部に変数を定義する事で、 関数内ローカルの変数として利用できる。
  1awk '{
  2        :
  3    # 関数 foo の定義
  4    #   num: ループ数
  5    # 以下ローカル変数
  6    #   i: ループウンタ
  7    function    foo(num,        i)
  8    {
  9        # i はローカル変数扱いなので呼出元の i は影響を受けない
 10        for(i=0; i<1num; i++)
 11            :
 12        }
 13    :
 14    foo(num);
 15        :
 16    }'
            
但し関数呼び出し時と関数定義時に引数の数が等しくないので、 後に混乱しないためにコメントで明記するなどの処置は必要。

2011/07/01

Keyboards

現在職場で愛用中のキーボード達。
改めて見ると個人所有のキーボードが沢山あって驚いた。

PFU Happy Hacking Keyboard PD-KB02

Image: RIMG0044.JPG

PFU Happy Hacking Keyboard PD-KB02

Happy Hacking Keyboard としては2代目の製品かな? いちばん古くから愛用しているキーボード。
メンプレンスイッチのキータッチと シリンドリカル・カーブドスカルプチャの構成は 今でもいちばん気に入っていて、 FreeBSD 端末に接続されている。 プログラムを書くときは、このキーボードと FreeBSD と vi が必須。

PFU Happy Hacking Keyboard Professional 2 PD-KB400WN

Image: RIMG0045.JPG

PFU Happy Hacking Keyboard Professional 2 PD-KB400WN

USB 接続タイプの新世代 Happy Hacking Keyboard。
静電容量無接点方式で押下圧が 45g なので、 キータッチは PD-KB02 に比べると若干軽く感じるが、 打鍵音が若干「カチャカチャ」気味なのが気になる。 シリンドリカル・ステップスカルプチャなので、 手を自然に置いた時の感じが PD-KB02 とは若干異なり 微妙な違和感を感じる。

Apple Wireless Keyboard MB167LL/A

Image: RIMG0043.JPG

Apple Wireless Keyboard MB167LL/A

薄型 Bluetooth 接続の Apple Wireless Keyboard で、 AA セルを 3 本利用する初代タイプ。
酸化皮膜処理のアルミニウムボディは非常に美しいのだが、 パンタグラフタイプなのでキータッチが軽すぎ、 しかもストロークが短いので打鍵感が頼りなく感じてしまい、 キー入力時に底打ちしてしまうのが微妙に使いづらい感じ。 以前は 27インチの iMac のメインキーボードとして活躍してた。 現在は自宅の TV に接続されている Mac MINI のキーボード。

Lenovo ThinkPad USB TrackPoint Keyboard 55Y9003

Image: RIMG0046.JPG

Lenovo ThinkPad USB TrackPoint Keyboard 55Y9003

かつての IBM Space Saver Keyboard の流れをくむ トラックポイントが搭載された薄型のキーボード。
こちらもパンタグラフタイプなのでキータッチが軽く、 ストロークも短めなので本家 IBM Space Saver Keyboard ほどは打鍵感が良くない。

Apple USB Keyboard

Image: RIMG0047.JPG

Apple USB Keyboard

USB 接続の Apple 社純正フルキーボード。
メンプレンスイッチの打鍵感は素晴らしく、 シリンドリカル・カーブドスカルプチャなので違和感を感じない。
テンキーが付いているフルキーボードは邪魔なのだが、 Macintosh 独特の特殊キー(コマンドキー)をクリックしながら 電源をオンにするといった特殊な用途のために USB 接続の純正キーボードが必要な場合がまれにあるので 手元に置いてある。

Fujitsu FKB8745-T101

Image: RIMG0041.JPG

Fujitsu FKB8745-T101

一部では割と有名な富士通高見澤製のキーボード。
メンプレンスイッチのキータッチと シリンドリカル・カーブドスカルプチャというのは PD-KB02 と同じ構成だ。
そもそも PD-KB02 も富士通高見澤製なので 打鍵感なども殆ど変わらない。 PD-KB02 にファンクションキーと カーソルキーを付けた様なものだと思う。
Windows マシンを操作する場合はカーソルキーやファンクションキーが あった方が楽なので手元に置いてあったのだが、 今は手元に Windows マシンがなくなってしまったので、 サーバルームのコンソール用に利用している (良いキーボードなので若干勿体ないな)。

PFU Happy Hacking Keyboard Type-S PD-KB400WNS

Image: RIMG0294.JPG

PFU Happy Hacking Keyboard Type-S PD-KB400WNS

前述の Happy Hacking Keyboard Professional の進化版。
従来のモデルに比較するとキータッチが格段に良くなっている。 カチャカチャ音が完全に消されていて 静かで心地よい音になっているので、 静かなオフィスでも気にせずにタイピングに集中できるし 何よりも打鍵音に安っぽさがなくなって非常に良い感じ。
しかも各キーの軸が安定していてブレる感じがないので キー入力時に全く不快感を感じなくなった。 Type-S という名称だけど全然別モノな感じでとても良い。 現在は iMac に接続されているが、 今の所 PD-KB02 と同じ位気に入った。
問題は高価な事かな。

2011/06/30

Bicycle

最近近所のお友達がちゃんとした自転車に乗るようになり、 一緒に遊ぶ度にその子の自転車を借りては乗っていた。
地面に足は付かないがペダルには届くので なかなか上手にペダルをこいで前に進んでいる姿を見ていると、 もう三輪車では間違いなく物足りない様なので 少し (随分) 早めの誕生日プレゼントとして自転車を買った。

Image: img_1204.jpg

a.n.design-works

アニメなどのキャラクターが描かれた自転車よりも、 シンプルで飽きのこないデザインの自転車が良いなと思い ネットで色々と調べてみると、 a.n.design-works というメイカーの自転車が 子供用とは思えない程シンプルで落ち着いたデザインだったので即決。

Image: img_1208.jpg

CV14

朝起きて自転車を目にした娘はそのまま室内で乗り回す程気に入った様だ。
これから暫くは幼稚園から帰ってくると乗り回す日々なんだろうが、 くれぐれも車には注意して安全に遊んで欲しいと心から願っている。

2011/06/27

MacBook Air のアップデート不具合

Mac OS X のアップデート 10.6.8 がリリースされていたので、 手元にある MacBook Air (Late 2010) でもアップデートを実施した。
MacBook Pro(Eary 2011) や職場の iMac 27″ (Late 2009) では 何も問題が発生しなかったのだが、 何故か MacBook Air だけは問題が発生してしまった。

10.6.8 へのアップデートは一見正常に終了したかに見えたが 最初の再起動ではログイン画面が表示されるまでに非常に時間がかかり、 なんとなく「イヤな予感」がしていたのだが、 ログイン画面が表示された瞬間に「イヤな予感」が的中した事を知った。
ログイン画面は白い半透明のフィルターがかかった様に表示されており、 マウスカーソルの移動はできてもクリックやキー入力は全くできなかった。
しょうがないので電源ボタンの長押しでシャットダウンして再度起動してみると、 やはりログイン画面が表示されるまでに非常に時間がかかり ログイン画面は今度は普通に表示されたのだが、 先ほど同様マウスカーソルの移動のみが可能でクリックやキー入力は 全く出来ない状況に変わりはなかった。

PRAMクリア
そこで電源スイッチを入れた直後に 『Command』+『Option』+『P』+『R』を同時に押して、 もう一度起動音が聞こえるまでキーを押し続ける PRAM クリアを実施してみるが状況は改善されない。
シングルユーザモード
次に電源スイッチを入れた直後に 『Command』+『S』を同時に押してシングルユーザモードで起動し、 Applejack を実行して ファイルシステムの整合性検証 (fsck)や アクセス権の修復などを実施してみるが状況は全く改善されない。
セーフブート
最後は起動音と同時に 『Shift』キーを押して起動する セーフブートを試みると何とかセーフモードで起動できたので、 ソフトウェアアップデートを確認してみると 10.6.8 が適用されていない状況だった。 そこで Apple のサイトから 10.6.8 のアップデータをダウンロードして 手動でインストールしてみたところ無事に起動できた。

PRAM クリアやアクセス権の修復では復旧できない障害はめずらしいが、 セーフモードで起動して回復できたので良しとする。
同じ症状で困っている人がいるかもしれないので記事として残しておきます。

2011/06/19

父の日

娘が幼稚園で作った父の日のプレゼント。

Image: RIMG0276.JPG

父の日のプレゼント

娘からプレゼントを貰えるなんて感激。
改めて成長しているんだなと実感する喜びの瞬間。

2011/06/16

太陽のたまご♪

今年も恒例の宮崎産の完熟マンゴー。

Image: IMG_1173.JPG

太陽のたまご

今年は娘もしっかりと食べる様になったので 1 個増やして 4 個買いました。
素晴らしい太陽と自然の恵みが詰まっています。

2011/06/15

php の proc_open() を利用した openssl コマンドの実行

php ネタ

openssl (1) で暗号化されたファイルを復号化する処理を php で実装する必要があった。
pear を探せばその手のモジュールは多分あるだろうと思ったが、 標準で含まれないモジュールに依存したくなかったので 外部コマンドの openssl を利用する方法を試してみた。

php では入力、もしくは出力のみの外部コマンド実行は popen() を利用できるが、 入出力双方向が必要なので proc_open() を利用する。
最初は proc_open() した openssl の入力側パイプに 暗号化されたデータを全て出力 (fwrite()) した後で 出力側パイプから復号化されたデータを読み出し (fread()) ていたのだが、 入力データがある程度のサイズを越えると openssl はデータ読込みの途中でデータを出力しないと 読込み (もしくは処理) をブロックしてしまう様なので、 fwrite() の後に fread() を実行する様に修正した。
この時、当初は stream_select() を利用してパイプの出力側からの 入力可否を監視する様にしたのだが、 stream_set_bloking() を利用してパイプの出力側を 非ブロックモードにする事で、 パイプから読込めない場合でも fread() が即リターンするので stream_select() の呼出しによりコードが煩雑になる事が避けられた。

  1<?php
  2    /*
  3     * Copyright (c) 2011 Mitzyuki IMAIZUMI. All rights reserved.
  4     *
  5     * $Id: decrypt.php 3 2011-06-16 16:15:48Z mitz $
  6     */
  7
  8    define("OPENSSL",    "openssl enc -d -des3 -pass pass:%s");
  9    define("BLOCSIZE",   "4096");
 10
 11    /*
 12     * ファイルの復号化
 13     *   $1: ファイル名
 14     *   $2: サイズ
 15     *   $3: パスフレーズ
 16     */
 17    function    decrypt($file, $size, $pass)
 18    {
 19
 20        $desc = array(
 21            0 => array("pipe", "r"),                /* stdin:  pipe */
 22            1 => array("pipe", "w"),                /* stdout: pipe */
 23            2 => array("file", "/dev/null", "w")    /* stderr: /dev/null */
 24        );
 25
 26        if(($fp = fopen($file, "r+"))){
 27            if($data = fread($fp, $size)){
 28                if(preg_match("/^Salted_/", $data)){
 29                    /* 暗号化されている場合 */
 30                    if($pp = proc_open(sprintf(OPENSSL, $pass), $desc, $pipe)){
 31                        /*
 32                         * `openssl enc -d …' を実行する。
 33                         *
 34                         * ファイルの内容はすでに $data に格納されているので
 35                         * BLOCSIZE 単位で openssl の標準入力に出力する。
 36                         */
 37
 38                        stream_set_write_buffer($pipe[0], 0);
 39                        stream_set_blocking($pipe[1], 0);
 40
 41                        $buf = "";
 42                        
 43                        while($size > 0){
 44                            /*
 45                             * 1 ブロック出力
 46                             * substr() は開始位置に負の値を指定すると
 47                             * 文字列の終端を起点とした開始位置からの
 48                             * 部分文字列が取得できる。
 49                             */
 50                            fwrite($pipe[0], substr($data, 0 - $size, BLOCSIZE));
 51                            $size -= BLOCSIZE;
 52                            /*
 53                             * openssl からの読み出し処理
 54                             * 非ブロッキングなので、
 55                             * 読めない場合は即座に fread() から戻る。
 56                             *
 57                            $buf .= fread($pipe[1], BLOCSIZE);
 58                        }
 59                        fclose($pipe[0]);
 60
 61                        while(!feof($pipe[1]))
 62                            $buf .= fread($pipe[1], BLOCSIZE);
 63                        fclose($pipe[1]);
 64
 65                        proc_close($pp);
 66                    }
 67                    /*
 68                     * 復号化したデータの出力
 69                     * 入力ファイルを書き換える
 70                     */
 71                    fseek($fp, 0);
 72                    ftruncate($fp, 0);
 73                    fwrite($fp, $buf);
 74                }
 75            }
 76            /* 暗号化されていない場合はそのまま close() する */
 77            fclose($fp);
 78        }
 79
 80    }
 81
 82?>
    

2011/06/16 追記

ブロック転送のロジックを整理して最適化した。
データサイズ $size をループの制御変数とする事で 余計な変数や転送ブロック数の計算を削除し、 openssl への出力データの部分文字列切り出し処理で substr() を利用する際に負の値を指定して 開始位置を文字列後端からの位置で指定する様に変更した。

2011/05/24

シェル変数への情報セット

例えば wget (1) コマンドへ proxy サーバの情報を伝えるためには http_proxy シェル変数に URL を http://[ID[:pass@]]FQDN[:port] 形式でセットする必要があるが、 proxy 情報が以下の形式でファイル格納されていれば 1 行で簡単にシェル変数に設定できる。

proxy.example.com                           # プロキシサーバの FQDN
8080                                        # プロキシサーバのポート番号
user                                        # プロキシサーバの認証 ID 
passwd                                      # プロキシサーバの認証パスワード
	
  1#!/bin/sh
  2
  3setproxy()
  4{
  5
  6    local   _var
  7
  8    _var=${1}
  9
 10    if [ -f ${2} ]
 11    then
 12        set -- `sed 's/#.*//g' ${2}`
 13        test -n "${1}" && eval "${_var}=\${1:+http_proxy=http://\${3:+\$3\${4:+:\${4}}@}\${1}\${2:+:\${2}}}"
 14    fi
 15
 16}
 17
 18setproxy http_proxy ファイル名
 19sh -c "${http_proxy} wget …"
 20    :
    


Copyright © 2008-2020 Mitzyuki IMAIZUMI. All rights reserved.