MySL改

インターンのエントリを書こうとしたら何故かMySLのエントリになりました(注:インターンでmyslを作ったわけではないです)。
※以下、予定を変更してお送りします。


ほぼ一年ぶりのエントリがmyslとか……。


myslについては
http://d.hatena.ne.jp/m-bird/20080623/1214231431

http://d.hatena.ne.jp/goth_wrist_cut/20080624/1214325754
を見て頂くとして、ちょいと改良(?)してみました。


前までのmyslは豊田氏のsl(http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/)にizumi氏のpatch(http://www.izumix.org.uk/sl/) を適応し、ncurses(http://ftp.gnu.org/pub/gnu/ncurses/)を同梱させて、Makefileを書き換えて、自己解凍シェルスクリプトを作って、というカオス仕様だったのですが、ライセンスどうよ?と作り替えましたとさ。
いや、個人的にはなかなかデキだと思うのですが、ね。


で、基本的にはよそ様のファイルはその都度ダウンロードしてきて、その場でmake、という方針。
やってることはそんな程度。
結構時間かかるからバックグラウンドで走らせたりするといいのかな?
見所(?)は汎用ダウンロード(?)ぐらいかな?
まぁ、書いたので一応上げてみた。

#!/usr/bin/env bash

fetchs="";

fetchs="${fetchs} wget";
function fetch_wget()
{
	local url="${1}";
	local output="${2}";
	wget -O"${output}" "${url}";
}

fetchs="${fetchs} fetch";
function fetch_fetch()
{
	local url="${1}";
	local output="${2}";
	fetch -o"${output}" "${url}";
}

fetchs="${fetchs} curl";
function fetch_curl()
{
	local url="${1}";
	local output="${2}";
	curl "${url}" > "${output}";
}

fetchs="${fetchs} dog";
function fetch_dog()
{
	local url="${1}";
	local output="${2}";
	dog "${url}" > "${output}";
}

fetchs="${fetchs} nc";
function fetch_nc()
{
	local url="${1}";
	local output="${2}";
	local prot="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\1#p;d'`";
	local host="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\2#p;d'`";
	local port="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\4#p;d'`";
	local path="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\5#p;d'`";
	if [ -z "${host}" ]; then return 1; fi
	(
	echo "GET ${url} HTTP/1.0\r\n";
	echo "Host: ${host}\r\n";
	echo "\r\n";
	) \
		| nc "${host}" "${port:=80}" \
		| sed '1,/^\s*$/d' > ${output};
}

fetchs="${fetchs} telnet"
function fetch_telnet()
{
	local url="${1}";
	local output="${2}";
	local prot="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\1#p;d'`";
	local host="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\2#p;d'`";
	local port="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\4#p;d'`";
	local path="`echo "${url}" | sed 's#\(http\)://\([^/:]*\)\(:\([0-9]*\)\)\?\(/.*\)#\5#p;d'`";
	if [ -z "${host}" ]; then return 1; fi
	(
	sleep 1; echo "GET ${url} HTTP/1.0";
	sleep 1; echo "Host: ${host}";
	sleep 1; echo "";
	sleep 2;
	) \
		| telnet "${host}" "${port:=80}" \
		| sed '1,/^\s*$/d' > ${output};
}

fetchs="${fetchs} error"
function fetch_error()
{
	echo "There are no way to fetch remote file.";
	exit 1;
}

function get_remote_file()
{
	local url="${1}";
	local output="${2}";
	for fetch in ${fetchs}; do
		if fetch_${fetch} "${url}" "${output}"; then
			fetchs="${fetch} error";
			return 0;
		fi
	done
	return 1;
}

# settings
install_dir="`mktemp -d ${HOME}/.sl-tmp.XXXXXXXX`";
bin_dir="${install_dir}/bin";
lib_dir="${install_dir}/lib";
include_dir="${install_dir}/include";

ncurses_url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz";
sl_url="http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/sl/sl.tar";
patch_url="http://www.izumix.org.uk/sl/sl5-1.patch";

ncurses_file="`basename "${ncurses_url}"`";
sl_file="`basename "${sl_url}"`";
patch_file="`basename "${patch_url}"`";

ncurses_dir="${install_dir}/ncurses-5.9";
sl_dir="${install_dir}/sl";

bash_aliases="${install_dir}/bash_aliases"
zsh_aliases="${install_dir}/zsh_aliases"
csh_aliases="${install_dir}/csh_aliases"

bashrc="${HOME}/.bashrc"
zshrc="${HOME}/.zshrc"
cshrc="${HOME}/.cshrc"

function die()
{
	echo "die: install failed";
	rm -fr "${install_dir}";
}

echo "${install_dir}";
export C_INCLUDE_PATH="${include_dir}:${C_INCLUDE_PATH}";
export LIBRARY_PATH="${lib_dir}:${LIBRARY_PATH}";
export PATH="${bin_dir}:${PATH}";

# fetch ncurses
cd "${install_dir}";
get_remote_file "${ncurses_url}" "${ncurses_file}" || die;
tar -xzf "${ncurses_file}" || die;

# make and install ncurses
cd "${ncurses_dir}";
./configure --prefix="${install_dir}" || die;
make || die;
make install || die;

# fetch sl
cd "${install_dir}";
get_remote_file "${sl_url}" "${sl_file}" || die;
tar -xf "${sl_file}" || die;

# patch and make, install
cd "${sl_dir}";
get_remote_file "${patch_url}" "${patch_file}" || die;
patch -f < "${patch_file}" || die;
make || die;
cp "${sl_dir}/sl" "${bin_dir}" || die;

# make aliases
cd "${install_dir}";
echo "export PATH=${bin_dir}" > "${bash_aliases}";
echo "export PATH=${bin_dir}" > "${zsh_aliases}";
echo "export PATH=${bin_dir}" > "${csh_aliases}";
PATHs="`echo ${PATH} | sed "s/:/ /g"`";
for i in `find ${PATHs} -maxdepth 1 -type f ! -iname alias` exit logout unalias alias; do
	# alias of alias must be last
	echo "\\\\alias '$(basename ${i})'='sl'" >> "${bash_aliases}";
	echo "\\\\alias '$(basename ${i})'='sl'" >> "${zsh_aliases}";
	echo "alias '$(basename ${i})' 'sl'" >> "${csh_aliases}";
done

# make backup and inject sl
if [ -f "${bashrc}" ]; then
	cp "${bashrc}" "${install_dir}";
	sed -i"" -e "1itest -f ${bash_aliases} && source ${bash_aliases} && return" "${bashrc}";
fi

if [ -f "${zshrc}" ]; then
	cp "${zshrc}" "${install_dir}";
	sed -i"" -e "1itest -f ${zsh_aliases} && source ${zsh_aliases} && return" "${zshrc}";
fi

if [ -f "${cshrc}" ]; then
	cp "${cshrc}" "${install_dir}";
	sed -i"" -e "1itest -f ${csh_aliases} && source ${csh_aliases} && return" "${cshrc}";
fi

echo "install done: ${install_dir}";

http://www.coins.tsukuba.ac.jp/~i0611238/mysl.sh
http://tinyurl.com/mysl-script
https://github.com/takei-yuya/mysl (7/12追記:githubにあげてみました)

多分だいたいの環境で動くとは思うのだけどテストしてない。
の、で、テストしてもらえると助かります。


telnetシェルスクリプトに組み込みづらくてしゃぁない。
sleepで適当に待ってるけど、環境によってはあれかも。


変更点としては、aliasを別ファイルにわけて、先頭でsourceするように。
これでrcファイル末尾にreturnを書くmysl除けのおまじないをしても効くようになりました。


あとaliasは手動で選ばずPATHにあるのを問答無用にぶち込むようにしました。
環境によっては時間かかるやも。
cshのaliasの勝手がわからなかったのでaliasのaliasは一番最後にするように。
bashzshだけなら必要ないんだけどナァ。
cshのbuiltinをクォート付きでaliasしたときの挙動がなんとも……。


加えてmktemp使うようにしたので、.slを先に作っておいてガードするのも不可。
だいぶ貫通力が増えたんじゃないかなぁ。


あ、念のため。
myslはセキュリティ意識向上を目的としたスクリプトであり、悪意をもって用いないように!
あと手元の環境でのテスト/実行は自己責任でお願いします。
念のため.(ba|z|c)shrcのバックアップを取っておくことをおすすめします。
一応バックアップを作るし、sedも先頭に追加する以外何もしないはずなんだけど……。


# そういや、myslって何も考えずに名前つけたけどMySQLに似てる……。