@znz blog

ZnZ の memo のようなもの

rubyのsample/cbreak.rbをSolarisで試した

| Comments

ruby の sample/cbreak.rb は Linux で試しても動かなくて、ファイルの頭に # ioctl example works on Sun と書いてあったので、 Solaris で試してみました。

vagrant box 探し

「vagrant solaris」で検索して https://vagrantcloud.com/boxes/search?q=solaris&utf8=%E2%9C%93 の中から plaurin/solaris-11_3 が比較的新しくて良さそうかなと思って使うことにしました。

VM 作成

適当なディレクトリを作成して vagrant init をしました。

mkdir solaris-11_3
cd solaris-11_3
vagrant init plaurin/solaris-11_3

説明ページに書いてあったので vi Vagrantfile

config.ssh.password = "1vagrant"

を追加しました。

vagrant up

してダウンロードなどを待ちます。

後は

vagrant ssh

で入って VM の中で作業しました。

git インストール

とりあえず git をインストールすることにしました。

https://git-scm.com/download/linux に書いてあったように

sudo pkg install developer/versioning/git

でインストールできました。

autoconf インストール

必要になるのがわかっているので autoconf もインストールしました。 パッケージ名は適当に指定してみたらインストールできました。

sudo pkg install autoconf

git clone

履歴はなくても良いので、 --depth 1 で最新だけとってきました。

git clone --depth 1 https://github.com/ruby/ruby

とりあえず configure

とりあえず configure まで実行するとエラーになりました。

vagrant@solaris:~$ cd ruby
vagrant@solaris:~/ruby$ autoconf
vagrant@solaris:~/ruby$ mkdir build
vagrant@solaris:~/ruby$ cd build
vagrant@solaris:~/ruby/build$ ../configure --prefix=$HOME/opt/ruby
checking for ruby... false
configure: error: cannot run /bin/sh ../tool/config.sub

baseruby をインストール

リリースされたアーカイブではないので、baseruby となる ruby が必要ということで ruby をインストールしてやり直しました。

vagrant@solaris:~/ruby/build$ sudo pkg install ruby
(略)
vagrant@solaris:~/ruby/build$ ../configure --prefix=$HOME/opt/ruby
checking for ruby... /usr/bin/ruby
downloading config.guess ... done
downloading config.sub ... done
checking build system type... i386-pc-solaris2.11
checking host system type... i386-pc-solaris2.11
checking target system type... i386-pc-solaris2.11
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/export/home/vagrant/ruby/build':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

gcc をインストール

C compiler がなくて、何を入れればいいのかよくわからなかったので、とりあえず gcc を指定してみたら入りました。

vagrant@solaris:~/ruby/build$ sudo pkg install gcc
(略)
vagrant@solaris:~/ruby/build$ ../configure --prefix=$HOME/opt/ruby
(略)
---
Configuration summary for ruby version 2.5.0

head: illegal option -- c
usage: head [-n #] [-#] [filename...]
/export/home/vagrant/opt/ruby
head: illegal option -- c
usage: head [-n #] [-#] [filename...]
${prefix}
head: illegal option -- c
(略)
head: illegal option -- c
usage: head [-n #] [-#] [filename...]
yes
head: illegal option -- c
usage: head [-n #] [-#] [filename...]
man

---

configure 自体は問題がなかったようですが、サマリーの表示部分でエラーになりました。

head -c を書き換え

head -c は POSIX になくて、代わりの手段を探してみたところ、どの環境でも使えるシェルスクリプトを書くためのメモ ver4.51 - Qiita の headコマンド にあったので head -c26dd bs=1 count=26 2>/dev/null に書き換えました。

vagrant@solaris:~/ruby/build$ cd ..
vagrant@solaris:~/ruby$ vi configure.in
vagrant@solaris:~/ruby$ autoconf
vagrant@solaris:~/ruby$ cd build
vagrant@solaris:~/ruby/build$ ../configure --prefix=$HOME/opt/ruby
(略)
vagrant@solaris:~/ruby/build$ make
(略)
generating parse.c
sh: line 1: bison: not found
*** Error code 127
The following command caused the error:
bison -d  -o y.tab.c parse.tmp.y
make: Fatal error: Command failed for target `parse.c'

bison インストール

リリースされたアーカイブだと不要なので configure ではチェックされない bison が必要だったのでインストールしました。

vagrant@solaris:~/ruby/build$ sudo pkg install bison
(略)
vagrant@solaris:~/ruby/build$ make
(略)
 compiling ../process.c
 ../process.c: In function ‘retry_fork_async_signal_safe’:
 ../process.c:3573:9: error: ‘fork’ is deprecated (declared at /usr/include/unistd.h:301) [-Werror=deprecated-declarations]
          pid = fork();
          ^
 ../process.c: In function ‘retry_fork_ruby’:
 ../process.c:3638:9: error: ‘fork’ is deprecated (declared at /usr/include/unistd.h:301) [-Werror=deprecated-declarations]
          pid = fork();
          ^
 ../process.c: At top level:
 cc1: warning: unrecognized command line option "-Wno-self-assign" [enabled by default]
 cc1: warning: unrecognized command line option "-Wno-constant-logical-operand" [enabled by default]
 cc1: warning: unrecognized command line option "-Wno-parentheses-equality" [enabled by default]
 cc1: warning: unrecognized command line option "-Wno-tautological-compare" [enabled by default]
 cc1: some warnings being treated as errors
 *** Error code 1
 The following command caused the error:
 gcc -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Werror=implicit-int -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration -Werror=deprecated-declarations -Wno-packed-bitfield-compat -Wsuggest-attribute=noreturn -Wsuggest-attribute=format -std=gnu99  -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -fexcess-precision=standard -DRUBY_EXPORT -fPIE   -I. -I.ext/include/i386-solaris2.11 -I../include -I.. -I../enc/unicode/9.0.0 -o process.o -c ../process.c
 make: Fatal error: Command failed for target `process.o'

fork が deprecated だということでエラーになりました。

-Werror=deprecated-declarations 削除

とりあえず今回試したい件とは関係ないので warnflags から -Werror=deprecated-declarations を削除しました。

vagrant@solaris:~/ruby/build$ sed -e 's/-Werror=deprecated-declarations//' Makefile > a
vagrant@solaris:~/ruby/build$ mv a Makefile
vagrant@solaris:~/ruby/build$ make
(略)
vagrant@solaris:~/ruby/build$ make install
(略)

sample/cbreak.rb の動作確認

動かしてみたら STDIN.ioctl(TIOCGETP, tty)Errno::EINVAL になりました。

vagrant@solaris:~/ruby/build$ export PATH=$HOME/opt/ruby/bin:$PATH
vagrant@solaris:~/ruby/build$ ruby -v
ruby 2.5.0dev (2017-05-02 trunk 58541) [i386-solaris2.11]
vagrant@solaris:~/ruby/build$ ruby ../sample/cbreak.rb
        from ../sample/cbreak.rb:30:in `<main>'
        from ../sample/cbreak.rb:9:in `cbreak'
        from ../sample/cbreak.rb:18:in `set_cbreak'
../sample/cbreak.rb:18:in `ioctl': Invalid argument @ rb_ioctl - <STDIN> (Errno::EINVAL)

TIOCGETP の確認

vagrant@solaris:~/ruby/build$ find /usr/include -name '*.h' | xargs grep TIOCGETP
/usr/include/sgtty.h:#define    TIOCGETP        (('t'<<8)|8)
/usr/include/sys/mtio.h:#define MTIOCGETPOS             (MTIOC|17)      /* Get drive position */
/usr/include/sys/termios.h:#define      TIOCGETP        (tIOC|8)
/usr/include/sys/ttold.h: * Structure for TIOCGETP and TIOCSETP ioctls.
/usr/include/sys/ttold.h:#define        TIOCGETP        (tIOC|8)
vagrant@solaris:~/ruby/build$ vi a.c
vagrant@solaris:~/ruby/build$ gcc a.c
vagrant@solaris:~/ruby/build$ ./a.out
7408
vagrant@solaris:~/ruby/build$ cat a.c
#include <sgtty.h>
#include <stdio.h>

int main() {
        printf("%x\n", TIOCGETP);
        return 0;
}

include するのが sys/termios.h でも sys/ttold.h でも 7408 でした。

sample/cbreak.rb では TIOCGETP = 0x40067408 なので、何か違うようです。

macOS で確認

そういえば macOS だとどうだろうと思って試してみたら、動いてしまいました。

ただし readline().print のところで sample/cbreak.rb:33:in `<main>': private method `print' called for "hoge\n":String (NoMethodError) でこけたので、直す必要がありました。

まとめ

ruby の sample はリリースに含まれていても、そのバージョンで動作確認されているとは限らないようです。

readline().printKernel#readlineString を返して、その Kernel#print を呼んでいるようなので、どのくらい古い ruby だと動くのか、それとも最初から動かなかったのか、よくわかりませんでした。

Comments