2017年5月27日土曜日

[FreeBSD] firefox 53.0.3とuimとgtk3

0. 要旨

2017年5月、Freebsd環境で、firefoxを53.0.3にportupgradeしたら、日本語が入力ができなくなった。
pkgsrcめも - isihara@るるる.おーぐのぺーじ
「uimにgtk3オプションを入れてmakeし直すと、入力できる。(デフォルトでは入っていない。)」
の記述をヒントに、
portupgrade -N textproc/uim-gtk3
したら日本語入力できるようになった。

1. 環境

OS:FreeBSD 11.1-PRERELEASE #2
Firefox: 53.0.3にversion upした。(穴はさっさと塞ぐべし。)
input method: uim※

※uimは昔から使っている。
~/.xsessionに以下を書いている。
export GTK_IM_MODULE=uim
export XMODIFIERS=@im=uim
uim-xim &

2. 状況と検索と試行錯誤

Firefoxのバージョンを上げたら、日本語が入力できなくなった。
atril(mateのpdf/ps viewer、gnomeのevinceにあたる)の検索窓には日本語を入力できる。
ということは、input method側の話ではないのかもしれない。

検索ワードを変えて、色々googleで検索する。
"firefox 53 日本語";それらしいものはみつからない。
"firefox nihongo";日本語が入らない人のために、"nihongo"が入るようにしているページを期待したが、とくにない。
"firefox input method":add-onの話ではないのだよ。
"firefox uim": FreeBSD + uim-anthy + Firefox | どうでもいいブログ - TeaCup
その情報、重要で記録に残していただいてありがたいのだけれど、その部分はすでに正しくなっている。

"firefox gtk_im_module":似た状況の人はいないようだ。それにしても、最近はuimはトレンディでないのかしら。

"firefox uim",1か月以内: pkgsrcめも - isihara@るるる.おーぐのぺーじ
 www/firefoxでuimで日本語入力できない [2017/5/6]
uimにgtk3オプションを入れてmakeし直すと、入力できる。(デフォルトでは入っていない。)
という記述がある。

BSDの話だし、時期も近いし、やってみようと思ってportsを見ると
textproc/uim-gtk
textproc/uim-gtk3
と2つある。何だこれは!uim-gtkしか入っていないぞ!と textproc/uim-gtk3もportsからインストールする。

rebootしたらfirefoxで日本語入力できるようになった。
めでたしめでたし。

先達のたった2行で解決できたことに感謝し、私も記録を残すこととする。

3. 推測

firefoxはしばらく前から、gtk2とgtk3の両方に依存しているようだが、
Input Methodまわりがgtk2からgtk3に変わったのかな。
(/usr/ports/graphics/atril/Makefileを見ると、atrilはgtk2に依存しているようだ。)

2016年12月10日土曜日

Canon PIXUS iP2700をFreeBSDからLPDで使う

0. 前置き

最近、うちのプリンタ(Canon BJ S500、2001年発売。2008年頃ヘッドを交換した)の調子が悪かった。

LEDで「サービスが必要なエラー」だと訴えかけてきて、バキバキと異音を発していたのだ。結局、分解して歯車を手で回したりしたら生き返ったのだが、治るまでの間に、後継機種がFreeBSDで使えるかを検討したので、その記録をここに公開する。

注意!!!実機では試していないので、本当に印刷できるかは確認していません!!!

1. 機種の選定

うちのプリンタは、
 出かけるときに地図を印刷する。
 論文等をちょっと印刷する。
 航空券などのeチケットを印刷する。
ような感じで、使っている。BJ S500で何も不満はない。

また、手元のFreeBSDビギナーズバイブル(改訂第2版、2005/09)[1]に記載されている非ポストスクリプトプリンタは、CanonのPIXUS 2機種である(なお、PIXUSは、Wonder BJシリーズの後継である)。これらの理由から、CanonのPIXUSを第1候補に考えた。

次に、Canonの「PIXUS選べるガイド」ページに行く。http://cweb.canon.jp/pixus/special/room/index.html?id=pix1 (公式サイトのPIXUSのトップhttp://cweb.canon.jp/pixus/からタイミング良くクリックするべし。)
「くらべてわかる早見表」から、iP2700で十分と思った。
価格.comを見ると、3000円代であり、これにしようと考えた。

[1] 後藤大地著、FreeBSDビギナーズバイブル、ISBN978-4839918941、http://www.amazon.co.jp/FreeBSDビギナーズバイブル-MYCOM-UNIX-Books-後藤/dp/4839918945

2. CUPS

FreeBSDでの印刷は、「CUPSプリンタドライバを使い、CUPSで印刷する方法」「LPD用のフィルタを使い、LPDで印刷する方法」の2つに大別される。

今のBJ S500はquantumの記録:FreeBSDからCanon BJ S500で印刷できた で書いたようにLPDで使っている。

前述したような用途で使っているので、pdfをatril経由で印刷するか、firefoxからpdfに保存して、atril経由で印刷することがほとんどである。したがって、CUPSはいらなくて、LPDで動けば十分である。(なお、ヘッドの位置合わせやスリープ設定等は、windows機でやればいいと割りきっている。)

一方、CUPSは色々できるが、構成が大きくて、動作させるまでもっていくのが大変そうである。(そもそもLinux用ドライバをFreeBSDで動かすのだ、困難は少ない方がいい。)

これらの理由から、iP2700のLPDでの動作確認をすることとした。

3. 予習

ビギナーズバイブルにはPIXUS iP4100が載っている。
「ip4100 linux」でググって、「Canon Bubble Jet Print Filter Ver 2.50 for Linux」のダウンロードページに行く。
共通パッケージ、機種別パッケージ、LPRng追加パッケージがダウンロードできるようになっていて、それぞれ、rpmがダウンロードされる。
tar xvf *.rpm で展開すると、usrディレクトリができる。(5年前から知っているけど、tarでrpmも展開できる)
ビギナーズバイブルを見ると必要なファイルは usr/local/bin/bjfilterpixusip4100 (あえて相対パスで書いた)で、それもusrディレクトリの下にできる。これはフィルタである。

4. iP2700のドライバを試す

前提条件

マシンはFreeBSD 11.0-stable #3。Linux互換も動くように設定してある。現在BJ S500が使えていて、使えるようにしたときの記録は、quantumの記録:FreeBSDからCanon BJ S500で印刷できた に公開している。
この記事の後、linux-baseをf10からc6に変更した。また、graphics/linux-f10-png10に穴が開いていて、portsで追いかけるのがしんどくなったので、必要なライブラリを確保して、パッケージをアンインストールしたあと、BJ S500のために必要最低限のライブラリだけを/compat/linux/usr/lib/に書き戻す作業もしている。(ノートに記録はあるのだが、blogでの公開はしていない。)
なお、前述のようにプリンタ本体はないので、印刷できるかまでは試していない。

4.0 ダウンロードする

「ip2700 linux」でググって、「IJ Printer Driver Ver.3.30 for Linux」のダウンロードページに行く。rpm版をダウンロードする。以下/tmp/にcnijfilter-ip2700series-3.30-1-i386-rpm.tar.gzをダウンロードしたとする。

4.1 展開する

まず展開する。
$ cd /tmp/
$ tar xvf cnijfilter-ip2700series-3.30-1-i386-rpm.tar.gz
/tmp/cnijfilter-ip2700series-3.30-1-i386-rpm/ ディレクトリができる。
その下に、install.sh、packages、resourcesがあって、packagesの下には、2つのrpmがあるので、とりあえず展開する。
$ cd cnijfilter-ip2700series-3.30-1-i386-rpm/packages
$ tar xvf cnijfilter-ip2700series-3.30-1.i386.rpm
$ tar xvf cnijfilter-common-3.30-1.i386.rpm
usr/ディレクトリができる。usr/local/bin/下にいくつかファイルがある。どれかがフィルタだとうれしい。どれだろう。lddしてみる。
$ ldd usr/local/bin/* |less
ここで、予習で用意したbjfilterpixusip4100のlddの出力と比較すると、usr/local/bin/cifip2700がフィルタのようだ。

4.2 動作させる

動作確認する。
Linuxバイナリのライブラリパスの設定とかやや面倒だから、/compat/の下に置いてしまう。
# cp usr/local/bin/cifip2700 /compat/linux/usr/local/bin/
動作確認には、今使ってる(/etc/printcapでif設定されている)/usr/local/libexec/canonを流用する。コピーして(canon_ip2700と名前を変えた)、フィルタ名を書き換えたものを次に示す。

#!/bin/sh

/usr/local/bin/gs \
    -q -r600 -dNOPROMPT -dSAFER -sPAPERSIZE=a4 -sDEVICE=ppmraw \
    -sOutputFile=- - quit.ps | \
    /compat/linux/usr/local/bin/cifip2700 --full --imageres 600 --lgmon

exit 0

おもむろに実行する
$ ./canon_ip2700
とライブラリ libcnbpcmcm364.soが足りないと言われる。
$ ls usr/lib/*
すると、libcnbpcmcm364.so.8.0.1と長いファイル名で、一式ライブラリファイルがあるが、短いファイル名のシンボリックリンクはない。tarなら、シンボリックリンク普通に使えるのになぜに?と思いながら作る。
$ cd usr/lib
$ for i in *.so do ln -s $i ${i%%.so.*}.so
/compat/の下にコピーする。
# cd ../../
# cp usr/lib/*.so* /compat/linux/usr/local/bin/

再挑戦する。
$ ./canon_ip2700
とライブラリ libpng12.so.0が足りないと言われる。portsから入れられそう。
$ ls -ld /usr/ports/*/*png*
すると、/usr/ports/graphics/の下に、linux-c6-png、linux-c7-png、linux-f10-pngがある。どれを使えばいいのだ?
$ pkg info -xI linux_base
linux_base-c6-6.8_6が現在のうちのマシンのlinux-base。5年前はf10だが変えたのだな。
# cd /usr/ports/
# portupgrade -N graphics/linux-c6-png

再挑戦する。
$ ./canon_ip2700
--lgmon: unknown optionと出た。ライブラリは揃って動き出したようだ。./canon_ip2700スクリプトから --lgmonを削除する。

再挑戦する。
<?xml version="1.0" encoding="utf-8" ?> (snip) </cmd>□□BJLSTART
ControlMode=Common
SetTime=2016 (snip)
BJLEND□

と出力始めるので、Ctrl-Cで止める。この出力は、今の/usr/local/libexec/canonとよく似ているので、とりあえず良さそうだ。

5. 補足

iP4100をLinux+lpdで使う場合にも、この記事は参考になるであろう。/compat/linux/を/(すらるーと)に読み替えて、portsの代わりにrpmなりを使えばよろしい。

2015年9月6日日曜日

バイナリファイルの可視化(ARMの機械語コードの縦縞が見たい!)

0. 要旨

「ARMの機械語コードをビットマップ表示のできるバイナリエディタで開いてみると、縦に線が見える」という噂がある。
しかし、hexeditにはそんな機能はない。そうだ、機械語コードにちょいっとヘッダをつけて、PNMファイルにしてしまおう。


1. ARMの機械語

最近、「熱血!アセンブラ入門」という本を読んでいる。
熱血!アセンブラ入門 サポートページからファイル一式も手に入れて、環境もばっちり整えて、ひたすらコード(ソースコードとアセンブリコードと機械語コード)で遊んでいるのだ。
そんな中でARMの機械語コードの縦線の話があるなら、やるしかない。

以下、登場する機械語コードは上記の熱血!アセンブラ入門 サポートページ
「環境構築の方法」で配布されている配布物を、うちでコンパイルしたものである。

2. PNM形式

PNM形式は画像形式の一種であって、4行(白黒なら3行)のヘッダの後に、ASCIIの数字、またはバイナリの数値を羅列した形式である。
(ASCII、バイナリ)と(白黒、グレイ、カラー)の直積で6種類があり、それぞれP1からP6のマジックナンバーが与えられている。wikipediaPNM画像の作成をご覧いただきたい。

単純な形式なので「そのバイトの値」を目で見るにはもってこいだ。
今回は、バイナリ、白黒のP4にする。

P4のファイル形式は、次のようになっている。
1行め:P4と書く
2行め:#と書く
3行め:横と縦のサイズを空白で区切って書く
4行め:ビット列が続く(0は白、1は黒で左上から右に順番に絵の色を指定していると解釈される)
拡張子は、P4だと白黒だから、pbmになる。

3. 画像にしよう

では、早速やってみよう。
サンプルコードをARM向けにコンパイルした実効形式のファイルがarm-elf.xである。

wc -c arm-elf.x|awk '{printf "P4\n#\n128 %d\n",$1/16}'>arm-elf.pbm ; cat arm-elf.x >> arm-elf.pbm

(コードは改行されているように見えるけれど、もちろん一行で。)
横のサイズを128にしたのは、hexeditを80x24のターミナルで開くと、1行を16byte=128bitで表示されるからである。

意図したとおりのヘッダがついたか確認してみよう。
$ less arm-elf.pbm
P4
#
128 877
^?ELF^A^A^Aa^@.....
よしできているようだ。

では画像として開こう。

4. 画像を見よう

eogでもemacsでもgimpでもdisplayでもpbmは認識される。
(ただし、displayとemacsではズームインの仕方がわからなった
emacsの虫眼鏡をクリックしたら、[I-search:]ですって)。
なお、eogはanti-aliasingがかかることがある。
Edit->Preferenceで Smooth image when zoomed-inのチェックを外しておこう。

全体像を次に示す(ブログにアップするために、pbmをpngにeogで変換した)。



左上で0と1との対応を確認しよう。
コードの最初の部分をhexeditと絵で次に示す。


arm-elf.xの始まりは
7F 45 4C 46 ...
だから
0111 1111 0100 0101  ...
だから
白黒黒黒 黒黒黒黒 白黒白白 白黒白黒 ...
と正しくなっているようだ。

機械語コードの部分をhexeditと絵を次に示す。
機械語部分は、0x1400バイトめ(320行め=0x1400/0x4、1行4バイトだから)から始まるので、そのあたりにズームインした。



よし。縦縞が見えた。

5. グレイスケールでも見てみよう

PNMのP4はグレイスケールの画像形式である。ここでは8ビットで1ピクセルを表すようにしてみよう。

wc -c arm-elf.x |awk '{printf "P4\n#\n16 %d\n",$1/16/8\n255}'>arm-elf.pgm ; cat arm-elf.x >> arm-elf.pgm

機械語コード部分を示す。


よし。縦縞だ。

6. まとめ

機械語コードは、catとawkで画像化できて、viewerで絵として見られる。

以上
(2016年12月10日、誤字修正)

2015年7月25日土曜日

gaucheでxmlから特定の要素を抜き出す

1. 背景

windosw updateをオフラインで実行する過程で、
オフラインのwindowsマシンは、windows updateの状況が書かれたXMLファイルを出力する。
出力されるファイルは次のようなものである。
<XMLOut>
  <CatalogInfo>
    <CreationDate>2015-07-14T04:38:16Z    </CreationDate>
  </CatalogInfo>
  <Check ID="500" Grade="2" Type="5" Cat="1" Rank="1" Name="Developer Tools, Runtimes, and Redistributables のセキュリティ更新プログラム" URL1="Help/Check5311.html" URL2="Help/Check5311fix.html" GroupID="48ce8c86-6850-4f68-8e9d-7dc8535ced60" GroupName="Developer Tools, Runtimes, and Redistributables">
    <Advice>不足しているセキュリティ更新プログラムが 2 個あります。
    </Advice>
    <Detail>
      <UpdateData ID="MS11-025" GUID="bb49cc19-8847-4986-aa93-5e905421e55a" BulletinID="MS11-025" KBID="2538242" Type="1" IsInstalled="false" Severity="3" RestartRequired="false">
    <Title>Microsoft Visual C++ 2005 Service Pack 1 再頒布可能パッケージのセキュリティ更新プログラム (KB2538242)
    </Title>
    <References>
      <BulletinURL>http://www.microsoft.com/technet/security/bulletin/MS11-025.mspx
      </BulletinURL>
      <InformationURL>http://go.microsoft.com/fwlink/?LinkId=216804
      </InformationURL>
      <DownloadURL>http://download.windowsupdate.com/msdownload/update/software/secu/2011/06/vcredist_x86_b8fab0bb7f62a24ddfe77b19cd9a1451abd7b847.exe
      </DownloadURL>
    </References>
      </UpdateData>
      <UpdateData ID="MS11-025" GUID="729a0dcb-df9e-4d02-b603-ed1aee074428" BulletinID="MS11-025" KBID="2538243" Type="1" IsInstalled="false" Severity="3" RestartRequired="false">
    <Title>Microsoft Visual C++ 2008 Service Pack 1 再頒布可能パッケージのセキュリティ更新プログラム (KB2538243)
    </Title>
    <References>
      <BulletinURL>http://www.microsoft.com/technet/security/bulletin/MS11-025.mspx
      </BulletinURL>
      <InformationURL>http://go.microsoft.com/fwlink/?LinkId=216803
      </InformationURL>
      <DownloadURL>http://download.windowsupdate.com/msdownload/update/software/secu/2011/05/vcredist_x86_470640aa4bb7db8e69196b5edb0010933569e98d.exe
      </DownloadURL>
    </References>
      </UpdateData>
    </Detail>
  </Check>
  (中略)
</XMLOut>

(もともとのファイルは改行があまりないので、blogに掲載するためにemacsのsgml-modeでsgml-pretty-printで整形した。)

ここで、各UpdateDataにおいて、IsInstalled="false"になっている項目を、DownloadURLからダウンロードしてくる必要がある。
さて、どうやろうか。手動でやるのは問題外である。
いろいろ方法はありそうだが、XMLのライブラリがあるscript言語を使ってみよう。
私が一番親しいscript言語は、Gaucheである。

2. Gaucheのxmlモジュール

GaucheにはXMLのためのモジュールがいくつかある。
今回は、sxml.ssax、sxml.sxpathでやりたいことがやれた。
詳しくは、Referenceを参照のこと。[1]

まず、ssax:xml->sxmlでファイルから読み込んだXMLをS式(sxml形式と読んでいる)に変換する。

(define (read-xml file-name)
  (call-with-input-file file-name
    (lambda (port)
      (ssax:xml->sxml port '() ))) )
は、XMLファイルを引数として受け取り、ファイル内のXMLと同じ構造のS式を返す関数を定義する。
ssax:xml->sxml の第3引数namespace-prefix-assigは
'()としたが問題は起きなかった。

次に、このS式を処理して必要なURLだけをファイルに書き出したい。
それにはsxpathが使える。
(sxpath '(XMLOut Check))は、(ルートから)XMLOut -> Checkとたどった時の要素のリスト(Checkがたくさんあることが想定されるから)を取り出すClosureを返す。

したがって、sxmlであるsxml-wholeに対して、((sxpath '(XMLOut Check)) sxml-whole)でXMLOut -> Checkとたどった時の要素のリストが返る。

3. まとめ

これらを組み合わせると、windowsの出力したXMLを食べて、必要なDownloadURLの一覧を出力するscriptができる。
#!/usr/local/bin/gosh 
(use sxml.ssax)
(use sxml.sxpath)

(define (read-xml file-name)
  (call-with-input-file file-name
    (lambda (port)
      (ssax:xml->sxml port '() ))) )
(define (get-url-unless-installed update-data)
  (if (string=? "false"
  (cadar ((sxpath '(|@| IsInstalled)) update-data)))
      (cadar
       ((sxpath '(References DownloadURL)) update-data))
      #f))

(define (main argv)
  (let ((sxml-whole (read-xml (list-ref argv 1))))    
    (map (lambda (y) (print  y))
  
  (filter (lambda (x) x) 
   (apply append
   (map (lambda (check)
          (map get-url-unless-installed
        ((sxpath '(Detail UpdateData)) check)))
        ((sxpath '(XMLOut Check)) sxml-whole))
   )
   ))
    ))

これで、gaucheでxmlから特定の要素を抜き出すことができた。

[1] Gauche ユーザリファレンス: 12. ライブラリモジュール - ユーティリティ
http://practical-scheme.net/gauche/man/gauche-refj_149.html#g_t_00e3_0083_00a9_00e3_0082_00a4_00e3_0083_0096_00e3_0083_00a9_00e3_0083_00aa_00e3_0083_00a2_00e3_0082_00b8_00e3_0083_00a5_00e3_0083_00bc_00e3_0083_00ab-_002d-_00e3_0083_00a6_00e3_0083_00bc_00e3_0083_0086_00e3_0082_00a3_00e3_0083_00aa_00e3_0083_0086_00e3_0082_00a3

2015年2月1日日曜日

気温と高度の関係

一般に「100m高くなると、0.6℃気温が下がる」言われている。

ところで、飛行機に乗るとエンターテイメント端末で、現在の高度、速度、外気温が表示できることがある。
最近、飛行機に乗る機会があったので、表示された高度、外気温、時刻をメモしてきた。
高度と外気温の関係をプロットしてみたものが図1である。



図1 気温と高度の関係

実線が離陸時、破線が着陸時のデータである。黒と青は往路と復路で別の日(いずれも1月の晴れの日)である。往路の到着地は、出発地から西に820kmの地点(復路は逆)。

注目するポイントがいくつかある。
1. 「100m高くなると、0.6℃気温が下がる」は、大体当てはまっているようだ。

2. 10000m付近で気温の低下が止まっている。対流圏界面が見えているかもしれない。

3. 1500mから2000m付近でグラフが折れまがっているものがある。空気のかたまりの境界を通過しているのかもしれない。
(青実線(day2,up)は2000m付近のデータが飛んでいる。雲はなかったので、見かけ上は温度一定だが、実際は黒破線(day1, down)と同様に一度上がっているかもしれない。)

教訓

「自分で」測定してみたわけではないけれど、データをさわってみると見えてくることがある。


参考文献

気象庁, "大気の構造と流れ", http://www.jma.go.jp/jma/kishou/know/whitep/1-1-1.html, 2015年2月1日閲覧

2014年9月21日日曜日

スクリプトの仕組み(いくつかの実験と考察)


私はscriptをよく使うのだが、scriptが走るときに具体的に何が起こっているのかを確認したいと思って、いくつか実験してみた。
(注意!!以下は、FreeBSDでの話です。)

実験1

スクリプト:hoge.scm
#!/usr/local/bin/gosh 
(define (main args)
  (print args))
実行結果
$ aho.scm
$ hoge.scm
(./hoge.scm)
$ gosh hoge.scm
(./hoge.scm)
interpreterにscriptを渡すのと、scriptを直接実行するのとは同じようだ。

実験2a

スクリプト:hoge.echo
hoge.echo
#!/usr/bin/echo
This is echo.
実行結果
$ ./hoge.echo 1 2 3
./hoge.echo 1 2 3
$ echo ./hoge.echo 1 2 3
./hoge.echo 1 2 3

実験2b

スクリプト:hoge.echo
#!/usr/bin/echo -n
This is echo.
実行結果
$ ./hoge.echo 1 2 3
./hoge.echo 1 2 3(改行なし)
$ echo ./hoge.echo 1 2 3
./hoge.echo 1 2 3(改行あり)

実験2c

スクリプト:hoge.echo
#!/usr/bin/echo -n that is echo
This is echo.
実行結果
$ ./hoge.echo 1 2 3
-n that is echo ./hoge.echo 1 2 3
$ echo ./hoge.echo 1 2 3
./hoge.echo 1 2 3
#!の後には、好きな実行ファイルが来ていいようだ。
しかし、echoはスクリプト名を引数として受け取ることは想定していないので、
$ echo filename
の形式は意味を成さない。

実験3a

スクリプト:hoge.c -> コンパイルしたものは hoge
#include < stdio.h >

int main(int argc, char **argv){
  int i;
  for(i=0; i;< argc; i++){
    printf("argv[%d]=%s\n", i, argv[i]);
  }
  return 0;
}  
実行結果
$ ./hoge 1 2 3
argv[0]=./hoge
argv[1]=1
argv[2]=2
argv[3]=3

実験3b

スクリプト:hoge.hoge
#!./hoge
実行結果
$ ./hoge.hoge 1 2 3
argv[0]=./hoge
argv[1]=./hoge.hoge
argv[2]=1
argv[3]=2
argv[4]=3

実験3c

スクリプト:hoge.hoge
#!./hoge -s
実行結果
$ ./hoge.hoge 1 2 3
argv[0]=./hoge
argv[1]=-s
argv[2]=./hoge.hoge
argv[3]=1
argv[4]=2
argv[5]=3

実験3d

スクリプト:hoge.hoge
#!./hoge -s witch
実行結果
$ ./hoge.hoge 1 2 3
argv[0]=./hoge
argv[1]=-s witch
argv[2]=./hoge.hoge
argv[3]=1
argv[4]=2
argv[5]=3

実験4

スクリプト:hoge.awk
#!/usr/bin/awk -f
BEGIN{
    for (i=0; i < ARGC; i++){
 print "ARGV[" i "]=" ARGV[i]
    }
}
実行結果
$ hoge.awk 1 2 3
ARGV[0]=/usr/bin/awk
ARGV[1]=1
ARGV[2]=2
ARGV[3]=3

$ awk -f hoge.awk 1 2 3
ARGV[0]=awk
ARGV[1]=1
ARGV[2]=2
ARGV[3]=3

結論

スクリプト:script
#! <interpeter>  <arg>
--- 
---

$ script argv1 argv2
として、実行されると、

裏では、(forkした後に)
argv[0] = <interpreter>
argv[1] = <arg>
argv[2] = script
argv[3] = argv1
argv[4] = argv2
として、execが実行される。
(ただし、<arg>が空の時には、
argv[0] = <interpreter>
argv[1] = script
argv[2] = argv1
argv[3] = argv2
と一個ずれる。)

別の書き方をすれば、次のようになる。
execve("script", "argv1", "argv2")
↓(shellが、scriptの最初の2バイトを読んで「scriptだ!」と気づく)
あらためて、
execve("<interpreter>", "<arg>", "script", "argv1", "argv2")
する。


スクリプト中の一行目の<args>はひとまとまりとして、<interpreter>に渡される。
したがって、<args>が空白で区切られたいくつかのフレーズを含んでも正しく解釈されない。
空白を含まないオプションを一つだけ与えたときのみ、意図した動きをする。
(実験2と実験3、/usr/src/bin/echo/echo.c)

interpreterがいわゆるスクリプト言語の場合は、argv1以降だけにトリミングして渡してくれるているので、interpreterにscriptを渡すのと、scriptを直接実行するので、同じように実行することができるようだ。
(sourceコードを見たのだけれど仕組みがわからなったので、誤解しているかもしれない。)
(実験1と実験4)

今のところは、考察は以上。

環境

OS:FreeBSD 9.3-STABLE r268734

以上

2014年9月14日日曜日

Arduinoとの通信(FreeBSDでのシリアル通信)

Arduinoが何かをしゃべるように、プログラムしたとする。
(例えば、Serial.println())を使う。)
何を喋っているかをTerminalで受け取るには、次のようにすればよい。
$ (stty speed 57600; cat) </dev/cuaU0
解説すると、標準入力(stdin)を/dev/cuaU0に切り替え、stty speedで、Arduinoが喋るスピードで耳を傾けるように設定する。
その後は、catによって、/dev/cuaU0から入力されたものを、terminalに表示する。

Arduinoを/dev/cuaU0として認識して、いきなりstdinに切り替えられるのは、 Arduino上の、FT232RL(FDTI社)のUSB-Serial変換石に対応した、 デバイスドライバがあるから。
FT232RLが乗っていないArudinoでは、うまくいかないかもしれない。
kernelが、USBに刺さったものをデバイスファイルに見えるように、 適当に/dev/cuaU0に割り当ててくれる。

stty speed 57600で terminal input baud rateを設定している。
Arduinoのプログラムで設定した値と合わせる必要がある。
baudは「ボー」と読む。

環境
OS:FreeBSD 9.3-STABLE r268734
ports:arduino-1.0.5_2,1, arduino-mk-0.10_1
arduino:CQカチャduino (Arduino Duemilanove互換)