Apple의 Mac OS X을 쓰는 사람들은 설치한 프로그램의 위치를 옮기거나 지우고 이름 바꾸는 일들을, 파일 다루기 이상의 특별한 작업으로 여기지 않습니다. 그것은 Mac OS X의 Finder가 Mail.app과 같이 여러 파일로 구성된 프로그램의 bundle 디렉토리를 하나의 단위로 다룰 수 있게 해주기 때문이지요. 프로그램 뿐 아니라, 가령 Keynote나 Pages의 문서도 여러 파일로 이루어진 디렉토리이지만 한 단위로 다룰 수 있습니다. 이러한 특징은 Time Machine이라는 백업도구가 파일을 단위로 변경사항을 기록하는 아주 단순한 방법으로도 매우 효율적으로 동작할 수 있는 기반이 됩니다. 이렇게 디렉토리를 하나의 파일처럼 다룰 수 있는 점을 저는 Mac OS X의 큰 장점으로 높이 평가해오고 있었습니다.
유닉스 철학을 따라서 프로그램을 짜다보면 자연스럽게 여러 파일로 만들게 됩니다. 프로그램을 여러 파일로 쪼개서 짤 때 생기는 좋은 일들이 많지만, 파일이 많으면 프로그램을 이리저리 들고다니기가 어려워 배포나 설치가 성가시다는 단점이 있습니다. 유닉스의 다중 파일 프로그램도 Mac OS X의 Finder에서처럼 하나의 파일처럼 취급할 수 있으면 좋겠다는 생각을 꾸준히 해오고 있었습니다. 그러다가 어제 dselect 목록에서 우연히 발견한 makeself라는 프로그램으로부터 영감을 받아 몇 자 끄적여봤습니다.
포장이라고 이름붙인 아래 프로그램은 darcs로 http://sparcs.org/~netj/pojang에서 받을 수 있습니다. 핵심이 되는 부분만 여기에 붙여봅니다.
#!/bin/sh -e
# pojang -- build an executable by packing given files and dirs
# Home: http://sparcs.org/~netj/pojang
# Author: Jaeho Shin <netj@sparcs.org>
# Created: 2008-03-13
#
# Usage:
# pojang <entry-file> [options>](<tar) <file>... > <executable>
# ...
entry=$1
# begin with the pojang driver
drvlen=`sed -ne '/<<DRV$/,/^DRV/p' <"$0" | wc -l | tr -d " "`
cat <<DRV
#!/bin/sh -e
# an executable packed with pojang -- http://sparcs.org/~netj/pojang
tmp=\`mktemp -d /tmp/pojang.XXXXXX\`
trap "rm -rf \$tmp" 0
tail -n +$drvlen "\$0" | tar pzxf - -C \$tmp
\$tmp/$entry "\$@"
exit \$?
DRV
echo "# end of pojang driver, package content follows"
# and the tar archive follows
tar zcf - "$@"
시작할 프로그램(entry)과 필요한 파일들을 인자로 주면, tar를 풀고 시작하는 셸 스크립트(driver)와 주어진 파일들을 묶은 tar 내용으로 구성된 셸 스크립트를 표준출력으로 내보내줍니다. 이를 파일에 저장하고 실행권한을 주면 여러 파일로 만든 프로그램을 하나의 실행파일로 묶을 수가 있는 것이죠.
묶은 셸 스크립트는 mktemp, tail, tar가 있어야 제대로 동작하며, pojang 자체는 tar, sed, wc, tr을 필요로 합니다. Debian 4.0과 Mac OS X 10.5에서 잘 동작하는 것을 확인했습니다. 아래와 같이 스스로를 포장하고 또 포장해도 잘 돌아갑니다. :)
p() {
: ${p:=./pojang}
$p $p >$p+
chmod +x $p+
p=$p+
}
p=
p;p;p;p;p;p;p
makeself나 sharutils도 있지만, 기본적으로 파일들을 묶고 푸는 일에만 초점을 맞춘 도구라 프로그램을 한 파일로 포장하는 일에는 부적합했습니다. makeself는 불필요한 출력을 없애기 어려웠고, shar는 풀자마자 실행할 파일을 지정할 수가 없었습니다. 그래서 pojang을 새로 만들었습니다.
프로그램의 무결성(integrity) 확인이나 라이센스 관리, DRM 적용 등도 이같은 방법으로 간단히 적용할 수 있지 않을까하는 생각이 들었습니다. 아무튼, 이제 pojang 덕분에, 프로그램을 여러 파일로 쪼개어 짜더라도 나중에 배포를 어찌하나하는 하는 걱정을 덜 수 있게 되었습니다.

netj
daybreaker