プログラミング環境としてNetBSDを使う話

# プログラミング環境としてNetBSDを使う話

[昨日の記事](http://qiita.com/furandon_pig/items/5479293cb21d6fd9f17c "NetBSDインストール後の環境設定")では、NetBSDにsshログインするまでの手順を書いてみました。今日はこの環境をプログラミングのために活用する内容で記事を書いてみようとおもいます。

## C言語でプログラミングする

NetBSDのインストール時に"Compiler Tools"という配布セットを選択すると、gccによる開発環境がインストールされます。
(一昨日のインストール手順は"Compiler Tools"を選択しています)

![img027.tiff.png](https://qiita-image-store.s3.amazonaws.com/0/61137/31cc4d8e-d901-c82d-c068-7b9744630450.png)

というワケで、C言語であれば、かなりお手軽にプログラミング環境ができあがります。

## シェルスクリプト

これも最初から利用できます、というよりもUNIX系OSであれば、どこでも利用できますね。bashやzshは後述するパッケージやpkgsrcでインストールします。

```sh
$ ls /bin/*sh
/bin/csh  /bin/ksh  /bin/sh
```

## パッケージで色々な言語をインストールして使う

### パッケージを検索...。

NetBSDもFreeBSDやOpenBSDやSolaris、Linuなんとか等のUNIX系OSと同じく、パッケージで様々なプログラミグ言語を利用できます。

が、残念なことにNetBSDのpkg_addではパッケージ名の検索ができません...。
(私の知識が無いだけで、検索用のコマンドやオプションは存在するかもしれません)

とはいえ、そこはUNIX系OS。上手いことサクッとパッケージ名を検索できるようにしてしまいましょう。

環境変数PKG_PATHにはパッケージが置かれているURLが入っているので、単にそこからHTMLをダウンロードして、grepで検索するだけでOKです(エレガントさは皆無ですが...)

```sh
$ sudo -i pkg_add w3m
$ w3m -dump ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/6.0/All > pkg_list.txt 
$ head -n10 pkg_list.txt 
Index of ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/6.0/All/

[Upper Directory]
.pkgcache . . . . . . . . . . . . . . . . . . . . . . . Dec  3 08:20  31.6M
0verkill-0.16nb1.tgz. . . . . . . . . . . . . . . . . . Nov 16 10:20   299K
2vcard-0.5nb3.tgz . . . . . . . . . . . . . . . . . . . Nov 15 21:59  9.51K
3ddesktop-0.2.9nb12.tgz . . . . . . . . . . . . . . . . Nov 17 17:58  82.4K
3proxy-0.5.3.11nb1.tgz. . . . . . . . . . . . . . . . . Nov 26 13:05  70.6K
4stAttack-2.1.4nb17.tgz . . . . . . . . . . . . . . . . Nov 27 13:15  1.80M
6tunnel-0.11rc2.tgz . . . . . . . . . . . . . . . . . . Nov 17 02:47  11.3K
```

こんな感じでパッケージを検索します。

```sh
$ grep ^nodejs pkg_list.txt 
nodejs-0.10.32.tgz. . . . . . . . . . . . . . . . . . . Nov 16 21:09  4.28M
```

### パッケージ関連コマンドの簡単な使い方

#### パッケージの追加

すでにコマンドの実行例で示していますが、パッケージをインストールする場合はpkg_addコマンドを使用します。

```sh
$ sudo -i pkg_add -v w3m
```

pkg_infoコマンドでインストールされているパッケージ名の一覧を取得できます。

```sh
$ pkg_info -a | head -n10
sudo-1.7.10p8       Allow others to run commands as root
readline-6.3nb3     GNU library that can recall and edit previous input
bash-2.05.2.9nb1    The GNU Bourne Again Shell (version 2)
perl-5.20.0nb2      Practical Extraction and Report Language
libatomic_ops-7.4.0nb1 Multi-platform library of atomic operations by Hans Boehm
boehm-gc-7.4.2      Garbage collection and memory leak detection for C and C++
w3m-0.5.3nb13       Multilingualized version of a pager/text-based browser w3m
libidn-1.29         Internationalized Domain Names command line tool
wget-1.16           Retrieve files from the 'net via HTTP and FTP
libyaml-0.1.6       YAML 1.1 parser and emitter written in C
```

特定のパッケージがインストールしたファイルを知りたい場合は、"pkg_info -L"とします。

```sh
$ pkg_info -L sudo
Information for sudo-1.7.10p8:

Files:
/usr/pkg/bin/sudo
/usr/pkg/bin/sudoedit
/usr/pkg/bin/sudoreplay
/usr/pkg/libexec/sudo_noexec.so
/usr/pkg/man/man5/sudoers.5
/usr/pkg/man/man8/sudo.8
/usr/pkg/man/man8/sudoedit.8
/usr/pkg/man/man8/sudoreplay.8
/usr/pkg/man/man8/visudo.8
/usr/pkg/sbin/visudo
/usr/pkg/share/doc/sudo/ChangeLog
/usr/pkg/share/doc/sudo/HISTORY
/usr/pkg/share/doc/sudo/LICENSE
/usr/pkg/share/doc/sudo/NEWS
/usr/pkg/share/doc/sudo/README
/usr/pkg/share/doc/sudo/TROUBLESHOOTING
/usr/pkg/share/doc/sudo/UPGRADE
/usr/pkg/share/doc/sudo/sample.pam
/usr/pkg/share/doc/sudo/sample.sudoers
/usr/pkg/share/doc/sudo/sample.syslog.conf
/usr/pkg/share/examples/sudo/sudoers
```

NetBSDでのアプリケーションインストール方法としては、コンパイル済みバイナリをインストールためのパッケージ(上記で説明している方法)と、ソースコードからアプリケーションをビルドして利用するpkgsrcという2つがあります。
pkgsrcについては、[@ebijun](https://twitter.com/ebijun "@ebijun")さんが12/8のAdvent Calendarにて[pkgsrcでソフトウェアをインストールする](https://github.com/ebijun/NetBSD/blob/master/Guide/pkgsrc.rst "pkgsrcでソフトウェアをインストールする")という記事を公開されていますのでぜひご覧ください。

## いろいろプログラミング言語を試してみる

いろいろなプログラミング言語がパッケージで提供されているので、Hello,Worldならぬ[四月は君の嘘](http://www.kimiuso.jp "四月は君の嘘")プログラムで試してみます。

### ruby

まずはruby。いくつかのバージョンが提供されていますね(EOLな1.8系があるのはたぶん目の錯覚...)

```sh
$ grep ^ruby pkg_list.txt | head -n4
ruby-1.8.7.374.tgz. . . . . . . . . . . . . . . . . . . Nov 22 21:18  1.57K
ruby-1.9.3p551.tgz. . . . . . . . . . . . . . . . . . . Nov 26 15:54  1.59K
ruby-2.0.0p598.tgz. . . . . . . . . . . . . . . . . . . Nov 26 15:28  1.58K
ruby-2.1.5.tgz. . . . . . . . . . . . . . . . . . . . . Nov 26 16:12  1.58K
```

ruby 2.1.5を試してみます。

```sh
$ sudo -i pkg_add -v ruby-2.1.5
$ ruby -e 'print "Your lie in April.\n"'
Your lie in April.
```

### Lua

次にLuaですが、これはNetBSDの標準配布セットにluaコマンドが含まれており、パッケージでLuaをインストールすると2つのバージョンのluaが存在する形になります。

```sh
$ grep ^lua[0-9]*-[0-9] pkg_list.txt
lua51-5.1.5nb1.tgz. . . . . . . . . . . . . . . . . . . Nov 12 14:36   343K
lua52-5.2.3nb1.tgz. . . . . . . . . . . . . . . . . . . Nov 12 14:45   377K
```

Lua 5.2を試してみます。

```sh
$ sudo -i pkg_add -v lua52-5.2.3nb1
```

/usr/bin/luaと/usr/pkg/bin/lua5.2がありますね。

```
$ ls -li `which lua`
2435606 -r-xr-xr-x  1 root  wheel  17592 Sep 29 16:37 /usr/bin/lua
$ ls -li `which lua5.2`
72197 -rwxr-xr-x  1 root  wheel  15944 Nov 12 14:45 /usr/pkg/bin/lua5.2
```

/usr/bin/luaのバージョンは5.1.4です。

```sh
$ /usr/bin/lua -v
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
```

こんな感じで動きます。

```sh
$ echo 'print "Your lie in April."' | /usr/bin/lua -
Your lie in April.
$ echo 'print "Your lie in April."' | /usr/pkg/bin/lua5.2 -
Your lie in April.
```

### python

(rubyと比べてパッケージが少ない気もしますが)Pythonも利用できます。

```sh
$ grep ^python pkg_list.txt
python26-2.6.9nb3.tgz . . . . . . . . . . . . . . . . . Nov 12 10:22  12.6M
python27-2.7.8nb1.tgz . . . . . . . . . . . . . . . . . Nov 12 08:12  14.8M
python33-3.3.5nb4.tgz . . . . . . . . . . . . . . . . . Nov 12 13:12  18.1M
python34-3.4.1nb1.tgz . . . . . . . . . . . . . . . . . Nov 12 12:59  20.4M
pythontidy-1.20nb1.tgz. . . . . . . . . . . . . . . . . Nov 16 06:21  26.2K
```

Pythonはバージョンがコマンドの末尾に付くので注意。

```sh
$ sudo -i pkg_add -v python34-3.4.1nb1
$ python3.4 --version
Python 3.4.1
$ python3.4 -c 'print("Your lie in April.")'
Your lie in April.
```

### Java

NetBSDではOpenJDKなJavaが利用できます。

```sh
$ grep jdk pkg_list.txt
openjdk7-1.7.65.tgz . . . . . . . . . . . . . . . . . . Nov 19 19:30  66.4M
openjdk7-bin-20090502.tgz . . . . . . . . . . . . . . . Nov 24 22:32  55.2M
$ sudo -i pkg_add -v openjdk7-1.7.65
```

バージョンは1.7.0です。

```sh
$ openjdk7-java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-pkgsrc_2014_11_19_18_55-b00)
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)
```

インストールされるjava関連コマンドは頭に"openjdk7-"が付きます。

```sh
$ ls /usr/pkg/bin/openjdk7-*
/usr/pkg/bin/openjdk7-jar               /usr/pkg/bin/openjdk7-orbd
/usr/pkg/bin/openjdk7-java              /usr/pkg/bin/openjdk7-policytool
/usr/pkg/bin/openjdk7-javac             /usr/pkg/bin/openjdk7-rmid
/usr/pkg/bin/openjdk7-javadoc           /usr/pkg/bin/openjdk7-rmiregistry
/usr/pkg/bin/openjdk7-javah             /usr/pkg/bin/openjdk7-servertool
/usr/pkg/bin/openjdk7-javap             /usr/pkg/bin/openjdk7-tnameserv
/usr/pkg/bin/openjdk7-keytool
```

例えばElasticsearcとかだと、./bin/elasticsearchスクリプトから"java"というコマンド名でjarファイルを起動する(というか、普通javaコマンドですね)ので、javaという名前でopenjdk7-javaコマンドのシンボリックリンクを作成しておくと良いかもしれません。

### PHP

PHPも複数のバージョンが提供されています。

```sh
$ grep ^php- pkg_list.txt | less 
php-5.3.29nb1.tgz . . . . . . . . . . . . . . . . . . . Nov 12 15:25  4.43M
php-5.4.35.tgz. . . . . . . . . . . . . . . . . . . . . Nov 23 11:29  4.84M
php-5.5.19.tgz. . . . . . . . . . . . . . . . . . . . . Nov 23 11:47  5.01M
```

```sh
$ sudo -i pkg_add -v php-5.5.19
$ php --version
PHP 5.5.19 (cli) (built: Nov 23 2014 11:47:13)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
$ php -r 'print "Your lie in April\n";'
Your lie in April
```

### JavaScript

JavaScriptの環境として、NodeJSが提供されています。

```sh
$ grep ^nodejs pkg_list.txt
nodejs-0.10.32.tgz. . . . . . . . . . . . . . . . . . . Nov 16 21:09  4.28M
$ sudo -i pkg_add -v nodejs
$ node --version
v0.10.32
```

```sh
$ node -e 'console.log("Your lie in April.");'
Your lie in April.
```

### R

Rもある(Rだけに)。

```sh
$ grep ^R-[0-9] pkg_list.txt
R-3.1.1.tgz . . . . . . . . . . . . . . . . . . . . . . Nov 19 20:28  36.9M
$ sudo -i pkg_add -v R-3.1.1
$ R --version
R version 3.1.1 (2014-07-10) -- "Sock it to Me"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: x86_64--netbsd (64-bit)
...
```

Rでも君嘘プログラム(初めてRのコードを書いた気がする)。

```sh
$ R

R version 3.1.1 (2014-07-10) -- "Sock it to Me"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: x86_64--netbsd (64-bit)
...
> print("Your lie in April.")
[1] "Your lie in April."
```

## NetBSDのプログラミング環境のもうひとつの楽しみ方

パッケージを使って様々なプログラミング言語を試してみるのも良いですが、NetBSDには、もうひとつの楽しみ方があります。
(楽しいと感じるかは個人差があります)

インストールされたNetBSDのコマンド群はシンボル情報が含まれており、objdump等で逆アセンブルした結果から元のソースコードを思い浮かべてみる、という楽しみ方です。

例えば、sleepコマンドを見てみます。

```sh
$ which sleep
/bin/sleep
$ file /bin/sleep
/bin/sleep: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for NetBSD 6.1.5, not stripped
```

objdump -dで逆アセンブルしてみます。main()の開始直後のあたりを眺めてみます。

```sh
$ objdump -d /bin/sleep
...
0000000000400df9 <main>:
  400df9:       55                      push   %rbp
  400dfa:       53                      push   %rbx
  400dfb:       48 83 ec 28             sub    $0x28,%rsp
  400dff:       89 fd                   mov    %edi,%ebp
  400e01:       48 89 f3                mov    %rsi,%rbx
  ...
  400e18:       be ee 0d 40 00          mov    $0x400dee,%esi
  400e1d:       bf 0e 00 00 00          mov    $0xe,%edi
  400e22:       e8 89 fd ff ff          callq  400bb0 <signal@plt>
  400e27:       ba 93 0f 40 00          mov    $0x400f93,%edx
  400e2c:       48 89 de                mov    %rbx,%rsi
```

0x400e22でsignal()を呼んでいるみたいなので、これを例に見てみます。
まずは0x400deeとかいうアドレスをesiレジスタに入れています。これはalarmhandleという関数のようです。

```sh
$ nm /bin/sleep | grep 400dee
0000000000400dee t alarmhandle
```

次に0xe(14)をediに入れています。

```sh
$ ruby -e 'printf("%d\n",0x0e)'
14
```

呼んでいるのはsignal()なので、シグナル番号なのでしょう。シグナル14番を調べると、SIGALRMのようです。

```sh
$ find /usr/include -type f \
> | grep signal \
> | xargs grep SIG \
> | grep 14 \
> | grep define
/usr/include/sys/signal.h:#define       SIGALRM         14      /* alarm clock */
```

ということは、0x400e18から0x400e22にかけてはsignal()の呼び出し処理で、おそらくSIGALRMをalarmhandle()という関数でハンドルさせる処理のように見えてきます。

/bin/sleepのソースコードで答え合わせすると、ばっちり予想通りで、少しだけバイナリを読むレベルが上がった気になれます。

```c
/usr/src/bin/sleep.c:
 68 main(int argc, char *argv[])
 69 {
 ...
 79         (void)signal(SIGALRM, alarmhandle);
```

こんな感じで、NetBSDはプログラミング環境だけでなく、バイナリを読むための練習環境としても活用できます。

## まとめ

今日の記事ではNetBSDをプログラミング環境として利用する方法を紹介してみました。明日からは[ryoon](http://qiita.com/ryoon "ryoon")さんによるAdvent Calendarとなります。ぜひお楽しみに。