NetBSD上のFirefoxで、KeePassXCと連携させてみる

この記事は、NetBSD Advent Calendar 2023の17日目の記事です。

KeePassXCとは

KeePassXCは、クロスプラットフォームなパスワード管理ソフトウェアです。 FreeBSD Workshopで、重村さんが紹介されていて、 それを聞いて詳しい機能を知ることができました。

パスワードをNetBSDデスクトップ環境で入力するのは、sudoやsuを使う時か、ウェブブラウザーでウェブサイトにログインする時が主だと思います。 sudoやsuで入力するパスワードの入力を補助してもらう必要はないので、入力補助が欲しいのはウェブブラウザー上のことになります。 KeePassXCは、Firefoxの拡張機能を経由して、KeePassXCアプリケーションと通信して、ユーザーIDやパスワードの情報を取得し、 ウェブフォームやBasic認証のポップアップに入力してくれる機能があります。

Firefoxにもパスワード管理機能はありますが、あくまでユーザーIDとパスワードの組み合わせを入力補助してくれる以上のことはできません。 3箇所以上に自動入力して欲しい時には、KeePassXCは役立ちそうです。

KeePassXCのインストール

NetBSDでは、pkgsrc/security/keepassxcとしてKeePassXCをインストールすることができます。 以下のように実行すれば良いでしょう。

# cd /usr/pkgsrc/security/keepassxc
# make install

pkgsrc/www/firefoxからインストールしてMozilla FirefoxでKeePassXC-Browser という拡張機能をインストールすれば、設定を開始する準備ができました。

KeePassXCの起動

KeePassXCの使い方は、KeePassXC: Getting Started Guideを読んでもらうのが一番です。 まずはパスワードデータベースを作成し、使う認証情報を登録してください。例えば下図のような感じです。

更に、設定画面からbrowser integrationを有効にし、Firefoxで使うように設定します。下図のような感じです。

KeePassXC-Browserの初期設定

まず、keepassxcコマンドでKeePassXCを起動させましょう。パスワードデータベースもロックを解除しておきます。 その上で、 ツールバーのジグソーパズルのピースのアイコンから、KeePassXC-Browserをクリックすると、最初にKeePassXCアプリケーションとの連携を設定する表示になります。 ここで、適当な識別子を入力して、Save and allow accessボタンを押してください。 これでKeePassXCアプリケーションとKeePassXC-Browser拡張機能がつながります。

KeePassXC-Browserを使ってみる

その上で、登録したウェブサイトを開くと、KeePassXCのアイコンが入力フォームに表示されます。同時に、どの情報を入力するかの選択のできるポップアップウィンドウが 表示されます。 ここで、利用したいものを選択すれば、自動的に認証情報が入力されます。

NetBSDで最新のMozcを使う 2

この記事は、NetBSD Advent Calendar 2023の20日目の記事です。

昨日に続き、Mozc 2.29.5268.102をNetBSD/amd64で使うまでの話を書きたいと思います。 ここで、NetBSD/amd64と書きました。 昨日は書き忘れてしまいましたが、Bazelは64ビットの環境でしかビルドできません。 ですので、NetBSD/i386に代表される32ビットの環境ではBazelが動かないので、 Mozc 2.29.5268.102をビルドすることはできません。残念です。

ちなみに、以前のMozcよりOSに依存するコードは格段に少なくなっているようです。 そういう部分はabseil-cppを利用することになったのかもしれません。 Bazelが良いためでないのは間違いありませんが…。

mozc-serverのビルド

Mozcのパッケージは、pkgsrc/inputmethod/mozc-serverからビルドしていくことになります。 実を言いますと、mozc-serverのビルドは難しくありませんでした。 潜在的なBazelの問題は、mozc-serverのビルドでは表面化しなかったのです。

ですが、以下のようにすれば、pkgsrc開発者的にはうれしいような気がします。

do-build:
        cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
                ${PREFIX}/bin/bazel \
                        --output_user_root=${WRKDIR}/bazel \
                        --client_debug \
                        build \
                        server:mozc_server \
                        --host_action_env=CWRAPPERS_CONFIG_DIR=${CWRAPPERS_CONFIG_DIR} \
                        --action_env=CWRAPPERS_CONFIG_DIR=${CWRAPPERS_CONFIG_DIR} \
                        --host_action_env=PATH=${PATH} \
                        --action_env=PATH=${PATH} \
                        --sandbox_debug \
                        --verbose_failures \
                        --subcommands \
                        --config oss_linux --compilation_mode opt

ここで、--output_user_rootをWRKSRC以下に設定すれば、make cleanすることで ビルドの過程で生成されたものは全て削除することができます。 また、--subcommandsを指定することで、どのようなコマンドが実行されたのか表示されるようになります。 ここで、oss_linuxというconfigを指定しているのですが、特にLinuxに特化したものではなく、 Unix-like OS全般に適用できるものでしたので、このままで大丈夫です。 --host_action_envや--action_envでcwrapperの変数を渡していますが、これは本当は不要でしょう。 Bazelはサンドボックス機能を持っているので、明示的に渡さないと環境変数も暗黙の内には引き継がれません。

これで、WRKSRC/bazel/bazel-out/netbsd-opt/bin/server/mozc_serverが生成できました。

mozc-rendererのビルド

次にはpkgsrc/inputmethod/mozc-rendererをビルドします。 pkgsrc以外のパッケージ管理の仕組みでは、mozc-rendererを個別のパッケージにしていない 場合もあるようですが、pkgsrcでは分けています。 この方が依存関係を解決するには良いと思うのですが…。

現在のMozcのmozc-rendererはQt6を利用しています。 Bazelではソースファイル(.cや.cxxなど)に加えて、そこからインクルードされる ヘッダーファイルまでBazelファイル中で再帰的に依存関係として記載しておく必要があります。 個人的には、そんな必要があるような気がしないのですが…。 しかもBazelファイルを記述するドメイン固有言語であるStarlarkではdir/**という そのディレクトリー以下のファイルを再帰的に指定する方法も提供されていますので、 自己否定しているような気もしてしまいます…。

いずれにしても、Qt6のようにツリー外の依存関係を解決するのは、Bazelでは少し面倒ですし、 一級市民ではないようです。 pkg-configの結果から、依存関係を自動生成する仕組みがMozc用に用意されていました。 ですが、少なくともNetBSD/amd64上のpkgsrcにとっては、指定されたパッケージでは 不足していました。WORKSPACE.bazelで、Qt6OpenGLとglもpkg-configで情報を 取得する対象にする必要がありました。

ここまでは、よくあることなのですが、実際にビルドしてみると、Qt6のヘッダーファイルが 不正に利用されているとしてBazelがエラーを多量に発生させてしまいます。 どうやら、cc -MDで生成される.dファイルの内容と、Bazelのサンドボックス機能で作られた ヘッダーファイルのパスが一致しているかをチェックしているようです。 例えば、/usr/pkg/qt6/include/QtCore/QObjectが不正に利用されていると エラーが発生していました。

いろいろと試してみると、2つのことが分かりました。 1つ目は、そもそも/usr/pkg/qt6という絶対パスはBazelファイルでの依存関係として 指定されていないと言うこと、2つ目は依存関係に絶対パスを指定するとBazelは絶対パスの 指定を許さずエラーになると言うことです。

Bazelは、ヘッダーファイルのパスを指定するのに、-Iではなく-isystemを利用します。 そして、各ヘッダーファイルは、シンボリックリンクでWRKSRC/bazel以下にBazelが配置します。 NetBSD/amd64-currentのGCC 10.5.0は、-isystemで絶対パスを設定し、それがシンボリックリンク を含んでいる場合に、シンボリックリンクをたどった結果のパスを.dファイルに記載するような 挙動になっていました。clangはそうではありません。

ここまで、NetBSD baseのccを使ってビルドするようにbazelをブートストラップしていたのですが、 GCCの挙動ではBazelは気にいらないようです。 pkgsrc/lang/clangからインストールされるclang/clang++を使うようにすることにしました。 これで正常にビルドは完了するようになりました。

mozc-tool、fcits5-mozcのビルド

mozc-rendererがビルドできれば、mozc-toolもfcitx5-mozcも問題なくビルドすることが できました。

今後について

Mozc自体はibus用のモジュールをビルドするようになっています。 私がfcitx5を利用しているので、今のところibus-mozcまでたどりついていませんが、 commitするまでには、ibus-mozcも用意しておきたいと思います。

NetBSDで最新のMozcを使う 1

この記事は、NetBSD Advent Calendar 2023の19日目の記事です。

はじめに

私自身はSKKを常用しているので、連文節日本語かな漢字変換の世間の流れを良く知りませんが、 Google日本語入力のオープンソース版であるMozcが、NetBSDで利用できるなかで、 一番快適なのではないかと思っています。

ですが、最近のProtocol Bufferパッケージ(pkgsrc/deve/protobuf)のアップデートで、 pkgsrc/inputmethod以下にあるMozc関連のパッケージがビルドに失敗するようになって しまったようです。

ちょうどpkgsrcは4半期のフリーズの時期ですので、実際にはアップデートはできていませんが、 Mozcを最新のタグである2.29.5268.102というバージョンにアップデートする準備が だいたい整いましたので、アップデートのために実施したことを書いておきたいと思います。

最近のMozcのビルドの仕組み

最近のMozcは、Googleの提供しているBazelというビルド・オートメーション・システムを 利用するようになっています。 pkgsrcに現在含まれているMozc関連のパッケージは、GYPというビルド・オートメーション・ツール を使っていましたが、少なくともNetBSDで利用する際にベースとなるLinuxでのビルドには、 GYPはもう使えないようです。

と言うことで、Bazelのパッケージを先に作成する必要があります。

Bazelのパッケージを作る

Bazelをビルドするには、2つの方法があるようです。 Bazelを使ってBazelをビルドする方法と、Bazelを使わずBazelをビルドする方法です。 NetBSD用のBazelバイナリーは配布されていませんので、後者の方法(ブートストラップする方法)を使うしかありません。 ブートストラップする場合には、Javaの.jarファイルが実行でき、Python 3も使えれば良いようです。

Bazelのソースコードを確認する

NetBSDでBazelをブートストラップしようとすると、NetBSDという選択肢がないとjavaコマンドに 文句を言われてしまい、先に進めません。 ブートストラップ用の配布物に含まれる.jarファイルがNetBSDに対応していないために、 このようなエラーが発生しているようです。 Bazelファイル(WORKSPACE、BUILD、*.bzl)と.javaファイルをLinuxやOpenBSD、FreeBSDでgrepし、NetBSDも同様に 定義をしたり、条件節を追加したりしてやります。 具体的な内容は、pkgsrc/wip/bazel/patches以下を見ていただければと思います。 この時点で気付いた以上のものが含まれてはいますが…。

Bazelのブートストラップ・キットを作り直す

.jarファイルの生成自体は、うまくBazelファイルを編集し、pkgsrc/pkgtools/libkverを 使えばNetBSDでもビルドできましたが、Linux/x86_64環境でビルドしてしまうのが一番簡単です。 bazel-distfileターゲットを実行すれば、.zipアーカイブでブートストラップ・キットが できあがるはずと思うのですが、scripts/bootstrap以下のファイルが含まれていませんでした。 これも元のブートストラップ・キットからコピーして再度手動でアーカイブファイルを作成し直して、 これをNetBSD環境へ持って行きます。 LOCAL_PORTS/bazel-6.4.0-dist-netbsd.tar.gzから最終的なブートストラップ・キットは 入手できます。 これ以降、Bazelファイルの修正が不足していて修正する必要が出て来るのですが、Bazelファイル を直しても、Linuxでブートストラップ・キットを作り直す必要はありませんでした。 修正して再度アーカイブ・ファイルを作成するだけで大丈夫でした。

Bazelの隔離機能とpkgsrcの隔離機能が競合する

Bazelは、一貫性のあるビルドを実行するために、ビルド用のサンドボックスを提供しているようです。 pkgsrcも、buildlink3という仕組みで、サンドボックス的な環境を提供しています。 ですが、2つの機能は少し発想が異なるようで、両立させるのは私には無理でした。

この時点で認識できた競合した事項を記載しておきます。

  • C/C++コンパイラーやstripコマンド等が絶対パスで埋め込まれてしまいます。 これによって、pkgsrcのcwrqapperのccコマンドやc++コマンド等をビルド時に使用すると、 WRKSRC以下の絶対パスがBazelコマンドに埋め込まれてしまい、実質的に使えないバイナリーに なってしまいます。
  • できたbazelバイナリーを実行してみて、libjava.soが見付からないとエラーが出るため JAVA_HOMEの設定がおかしい、あるいはどこかで上書きされているのではないかと、 この時は考えていたのですが、これは勘違いでした。

Bazelのランタイムエラーを解析し、修正する

生成されたbazelコマンドを実行すると、

Error: could not find libjava.so
Error: Could not find Java SE Runtime Environment.

と表示されて、動きません。 検索すると、 Java error on AIX #6655 に同じ問題に悩んでいるAIXへ移植しようとしている人がいたのですが、 解決することなくissueはクローズされてしまっています。

何もヒントがウェブ上にはないようなので、lang/openjdk11でこのエラーメッセージを 出している箇所を検索してみることにしました。

すると、 jdk11u-jdk-11.0.21-9-1/src/java.base/unix/native/libjli/java_md_common.c の中の、以下の関数のdladdr()が想定されるlibjli.soのパスではなく、bazel()という文字列を 返しているのが良くないと分かりました。

jboolean
GetApplicationHomeFromDll(char *buf, jint bufsize)
{
    /* try to find ourselves instead */
    Dl_info info;
    if (dladdr((void*)&GetApplicationHomeFromDll, &info) != 0) {
        char *path = realpath(info.dli_fname, buf);
        if (path == buf) {
            return TruncatePath(buf);
        }
    }
    return JNI_FALSE;
}

lang/oprnjdk11では、libjliは静的にリンクされています。 それがいけなさそうです。

jdk11u-jdk-11.0.21-9-1/make/launcher/LauncherCommon.gmk を見ると、AIXとBSDの場合は、libjliを静的にリンクするようになっています。 さきほどのissueでAIXの人が同じように悩んでいたのも納得できました。 https://mail-index.netbsd.org/pkgsrc-changes/2023/12/09/msg288356.html のように変更し、lang/openjdk11でlibjli.soを動的にリンクするようにしました。 実際には、 https://mail-index.netbsd.org/pkgsrc-changes/2023/12/12/msg288501.html の適用も必要でした。

このopenjdk11を使えば、bazelコマンドは正常に動作しているように見えるくらいにはなりました。

時間の関係で、更にbazelを直しつつ、Mozcをビルドする話は次回に続きます。

NetBSD上のFirefoxで、text-to-speechを試す

この記事は、NetBSD Advent Calendar 2023の1日目の記事です。

はじめに

最近のMozilla Firefoxには、text-to-speech機能を利用するための仕組みが組み込まれています。 しかし、Firefox自体がテキストの内容を発音する訳ではなく、speech-dispatcher経由でFestivalというtext-to-speechエンジンを利用します。 NetBSDでも、pkgsrcを使ってFirefoxやspeech-dispatcher、Festivalをインストールし、設定することで、この機能を利用できます。 ですが、音声の品質は良くないようです。 今回は英語のみ発音させることを考えます。

Firefoxのインストール

現在のpkgsrc/www/firefoxのバージョンは120.0です。 既定値ではspeech-dispatcherを使うオプションは有効化されていません。 今回紹介する手順を実施しておかないと、text-to-speechが使えないという警告が頻繁に表示されることがあるので、speech-dispatcherを使うオプションはtext-to-speech機能を利用したい人だけが有効化するのが良いと思います。

以下のように/etc/mk.confに記載して、speech-dispatcherを利用できるFirefoxをビルドできるようにします。

# vi /etc/mk.con
PKG_OPTIONS.firefox=speechd

これを設定した上で、pkgsrc/www/firefoxをビルドし、インストールします。

# cd /usr/pkgsrc/www/firefox
# make install

speech-dispatcherは、pkgsrc/audio/speech-dispatcherにありますが、自動的にインストールされます。

Festivalのインストール

Festivalは本体であるpkgsrc/audio/festivalだけではなく、発音データは音声データも必要です。 pkgsrcでインストールする場合には、以下の4つのパッケージをインストールすれば、Festival本体も含め必要なものは全てインストールできます。

  • pkgsrc/audio/festvox-kal16
  • pkgsrc/audio/festvox-ked16
  • pkgsrc/audio/festvox-rab16
  • pkgsrc/audio/festival-freebsoft-utils

以下のように操作すれば良いでしょう。

# cd /usr/pkgsrc/audio/festvox-kal16
# make install
# cd /usr/pkgsrc/audio/festvox-ked16
# make install
# cd /usr/pkgsrc/audio/festvox-rab16
# make install
# cd /usr/pkgsrc/audio/festival-freebsoft-utils
# make install

これにより、3つの音声を選択することができるようになります。 いずれもあまり質は良くないのですが‥、

speech-dispatcherの設定

speech-dispatcherは、標準ではespeak-ngを使うような設定ファイルになっています。 今回はFestivalを使いますので、そのように指定して行きます。 /usr/pkg/etc/speech-dispatcher/speechd.confに、以下のようなパッチを適用すれば良いでしょう。

--- /usr/pkg/share/examples/speech-dispatcher/speechd.conf	2023-11-18 05:59:28.000000000 +0900
+++ /usr/pkg/etc/speech-dispatcher/speechd.conf	2023-12-01 12:33:15.988361377 +0900
@@ -114,6 +114,7 @@
 # configuration.
 
 # DefaultLanguage "en-US"
+DefaultLanguage "en-US"
 
 
 # ----- MESSAGE DISPATCHING CONTROL -----
@@ -255,7 +256,7 @@
 
 #AddModule "espeak"                   "sd_espeak"    "espeak.conf"
 #AddModule "espeak-ng"                "sd_espeak-ng" "espeak-ng.conf"
-#AddModule "festival"                 "sd_festival"  "festival.conf"
+AddModule "festival"                 "sd_festival"  "festival.conf"
 #AddModule "flite"                    "sd_flite"     "flite.conf"
 #AddModule "ivona"                    "sd_ivona"     "ivona.conf"
 #AddModule "pico"                     "sd_pico"      "pico.conf"
@@ -287,7 +288,8 @@
 # The DefaultModule selects which output module is the default.  You
 # must use one of the names of the modules loaded with AddModule.
 
-DefaultModule espeak-ng
+#DefaultModule espeak-ng
+DefaultModule festival
 
 # The LanguageDefaultModule selects which output modules are prefered
 # for specified languages.
@@ -295,6 +297,7 @@
 #LanguageDefaultModule "en"  "espeak"
 #LanguageDefaultModule "cs"  "festival"
 #LanguageDefaultModule "es"  "festival"
+LanguageDefaultModule "en"  "festival"
 
 # -----CLIENT SPECIFIC CONFIGURATION-----
 

起動させる

Firefoxを起動させる前に、Festivalサーバーを起動しておく必要があります。 Festivalサーバーは、/etc/rc.d以下のスクリプトで起動させるのではなく、自分で起動させる必要があります。

$ festival --server &

続いて、Firefoxも起動させます。

$ firefox &

テキストを読ませる

テキストを読ませるには、リーダービュー機能が利用できるウェブページである必要があります。 例えば、https://edition.cnn.com/の個別の記事であれば、リーダービューを有効にできます。 アドレス欄の右端に下図のようなアイコンが表示されていれば、リーダービューを利用できるウェブページです。 これをクリックすると、リーダービュー画面に移動することができます。

リーダービュー画面では左上に、下図のようなコンソールが表示されています。 ヘッドホンアイコンをクリックすると、音声や再生速度の選択、再生・停止の指示のできるポップアップもできます。

pkgsrc/mail/dkimproxyを使ってみたが、受信時の動作は、現在の用途には合わないようだった

とある過去に利用者のいたドメインを所有しているのだが、相当に雑な運用だったようで、いまだにSPAM以外の電子メールが来るし、 そのドメインの存在しないアカウントを装った電子メールが多く送信されているようだった。 しばらく、キャッチオール設定をして受信してみて気付いた...