Termuxにisync(mbsync)を導入

# 序

Androidでgmailを扱うアプリはいくつかあるんですが、わたしが試したアプリはどれも、メールが多くなってくるとある程度過去のメールが見えなくなる(取得できなくなる)ので、`isync`を試してみることにしました(最初は`emacs`の`gnus`を検討したんですが、機能の膨大さにより諦めました)。

基本的には、[ここ](https://wiki.termux.com/wiki/Package_Management#Working_with_packages)の手順にしたがってインストールしました。

(2018/02/07加筆)
<details><div>
isyncのパッケージ化は1年程前から`termux-packages`のissueがオープンされてたようで、この記事の修正を元にpullリクエストをだしたところ、めでたくマージされました。なので、`pkg update && pkg install isync`でインストールできるはずです。
</details></div>

# ビルドツールのインストール

ソースをビルドするためのパッケージをインストールします。

```shell-session
$ pkg install autoconf automake bison bzip2 \
              clang cmake coreutils diffutils \
              flex gawk git grep gzip libtool \
              make patch perl sed silversearcher-ag \
              tar termux-exec wget
Hit:1 https://termux.net stable InRelease
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.
Reading package lists... Done
Building dependency tree
Reading state information... Done
.....
```

# 依存パッケージの導入

## `readline-dev`のインストール

後述の`drv_imap.c`の修正により必要となる`readline-dev`をインストールします。

```shell-session
$ pkg install readline-dev
Hit:1 https://termux.net stable InRelease
Reading package lists... Done
Building dependency tree
Reading state information... Done
.....
```

## `openssl-dev`のインストール
これなしでもビルドはできますが、SSLをサポートしないので、`configure`する前に`openssl-dev`をインストールします。

```shell-session
$ pkg install openssl-dev
Hit:1 https://termux.net stable InRelease
Reading package lists... Done
Building dependency tree
Reading state information... Done
.....
```

# `isync`のビルド

## ソースの取得

[ここ](https://sourceforge.net/projects/isync/files/isync/1.3.0/)から`isync`のバージョン1.3.0をダウンロードしました。ダウンロードしたら解凍して、解凍したフォルダーに移動します。

## `config.sub`と`config.guess`のコピー
`Termux`版の`libtool`の`config.sub`と`config.guess`をソースの解凍フォルダーにコピーします。

```shell-session
export PREFIX=/data/data/com.termux/files/usr
export LD_PRELOAD=${PREFIX}/lib/libtermux-exec.so
$ cp ${PREFIX}/share/libtool/build-aux/config.sub .
$ cp ${PREFIX}/share/libtool/build-aux/config.guess .
```

## ソースの修正

### ハードコーディングされているパスの修正

ソース内にハードコーディングされているパスを修正します。

#### `src/compat/config.c`の修正

```diff:config.c.patch
diff -u -r isync-1.3.0.orig/src/compat/config.c isync-1.3.0/src/compat/config.c
--- isync-1.3.0.orig/src/compat/config.c	2017-10-01 17:42:35.000000000 +0900
+++ isync-1.3.0/src/compat/config.c	2018-02-05 14:08:09.779837587 +0900
@@ -451,7 +451,7 @@
 					goto gotstor;
 			box->local_store_path = my_strndup( path, pl );
 			/* derive a suitable name */
-			if (!strcmp( box->local_store_path, "/var/mail/" ) || !strcmp( box->local_store_path, "/var/spool/mail/" )) {
+			if (!strcmp( box->local_store_path, "/data/data/com.termux/files/usr/var/mail/" ) || !strcmp( box->local_store_path, "/data/data/com.termux/files/usr/var/spool/mail/" )) {
 				local_store = nfstrdup( "spool" );
 			} else if (!strcmp( box->local_store_path, "~/" )) {
 				local_store = nfstrdup( "home" );
```

#### `src/compat/main.c`の修正

```diff:main.c.patch
diff -u -r isync-1.3.0.orig/src/compat/main.c isync-1.3.0/src/compat/main.c
--- isync-1.3.0.orig/src/compat/main.c	2017-10-01 17:42:35.000000000 +0900
+++ isync-1.3.0/src/compat/main.c	2018-02-05 14:07:41.339837597 +0900
@@ -384,7 +384,7 @@
 			return 1;
 		}
 	} else {
-		strcpy( path2, "/tmp/mbsyncrcXXXXXX" );
+		strcpy( path2, "/data/data/com.termux/files/usr/tmp/mbsyncrcXXXXXX" );
 		if ((fd = mkstemp( path2 )) < 0) {
 			sys_error( "Error: cannot create temporary config file" );
 			return 1;
```

#### `src/socket.c`の修正

```diff:socket.c.patch
diff -u -r isync-1.3.0.orig/src/socket.c isync-1.3.0/src/socket.c
--- isync-1.3.0.orig/src/socket.c	2017-10-01 17:42:35.000000000 +0900
+++ isync-1.3.0/src/socket.c	2018-02-05 14:08:37.529837576 +0900
@@ -398,7 +398,7 @@
 				_exit( 127 );
 			close( a[0] );
 			close( a[1] );
-			execl( "/bin/sh", "sh", "-c", conf->tunnel, (char *)0 );
+			execl( "/data/data/com.termux/files/usr/bin/sh", "sh", "-c", conf->tunnel, (char *)0 );
 			_exit( 127 );
 		}
```

### Android固有の問題にたいする修正

#### `drv_imap.c`の修正

bionic libcのライブラリーにない`getpass`関数を追加します。[ここ](https://github.com/termux/termux-packages/blob/master/packages/unrar/getpass.patch)を参考にしてソースを修正しました。

```diff:drv_imap.c.patch
diff -u -r isync-1.3.0.orig/src/drv_imap.c isync-1.3.0/src/drv_imap.c
--- isync-1.3.0.orig/src/drv_imap.c	2017-10-01 17:42:35.000000000 +0900
+++ isync-1.3.0/src/drv_imap.c	2018-02-05 14:06:55.819837615 +0900
@@ -36,6 +36,9 @@
 #include <time.h>
 #include <sys/wait.h>
 
+#include <termios.h>
+#include <readline/readline.h>
+
 #ifdef HAVE_LIBSASL
 # include <sasl/sasl.h>
 # include <sasl/saslutil.h>
@@ -251,6 +254,33 @@
 	"Deleted",
 };
 
+#ifdef __ANDROID__
+static char* getpass(const char *prompt) {
+  struct termios term_old, term_new;
+  int nread;
+
+  /* Turn echoing off and fail if we can't. */
+  if (tcgetattr (0, &term_old) != 0) {
+    return NULL;
+  }
+  
+  term_new = term_old;
+  term_new.c_lflag &= ~ECHO;
+  
+  if (tcsetattr (0, TCSAFLUSH, &term_new) != 0) {
+    return NULL;
+  }
+
+  /* Read the password. */
+  char *password = readline(prompt);
+
+  /* Restore terminal. */
+  (void) tcsetattr (0, TCSAFLUSH, &term_old);
+
+  return password;
+}
+#endif
+
 static imap_cmd_t *
 new_imap_cmd( int size )
 {
```

## ビルド

### `configure`する

`configure`します。リンクするライブラリーに先程インストールした`readline`を指定します。デバッガなどで追いたい場合は`CFLAGS=-g`とかを追加指定します。

```shell-session
$ ./configure --prefix="${PREFIX}" CC=clang CXX=clang++ LIBS='-lreadline'
checking for a BSD-compatible install... /data/data/com.termux/files/usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /data/data/com.termux/files/usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
.....
```

### `make`してインストール

```shell-session
$ make install
Making install in src
make[1]: Entering directory '/data/data/com.termux/files/home/src/isync-1.3.0/src'
make[2]: Entering directory '/data/data/com.termux/files/home/src/isync-1.3.0/src'
clang -DHAVE_CONFIG_H -I. -I..   -D_GNU_SOURCE   -g -O2 -pipe -W -Wall -Wshadow -Wstrict-prototypes -std=c99 -pedantic -Wno-overlength-strings -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
clang -DHAVE_CONFIG_H -I. -I..   -D_GNU_SOURCE   -g -O2 -pipe -W -Wall -Wshadow -Wstrict-prototypes -std=c99 -pedantic -Wno-overlength-strings -MT sync.o -MD -MP -MF .deps/sync.Tpo -c -o sync.o sync.c
.....
```

# 結び

これでインストールは終了です。次は[muをインストール](https://qiita.com/ayatakesi/items/8ff7fa63ba2eb9bff8e0#_reference-bcd15e96ead2d396bfe8)して[mu4eでメール](https://qiita.com/kaz-yos/items/164f03c7bba401646783)な環境を構築したいです。おわり