PHPでiCalendarなデータをパースする

PukiWikiにGoogleカレンダーのデータを表示したかったんだけど、それらしいプラグインがいまいち見つからなかったので自前で書くことにした。

Googleカレンダーでicsファイルへのリンクを取得して、それをプラグインで読み込んで、あとはてきとうにパースして整形して〜と思っていたけど、パース書くの面倒だなぁと思ってぐぐったら、File_IMCを使えば良いようなので使うことにした。

File_IMCはPearを通してインストールする…がPearもデフォルトでは入っていないのでインストールしよう。

環境はUbuntu 16.04.2

$ sudo apt-get install php-pear
$ pear list
Installed packages, channel pear.php.net:
=========================================
Package Version State
Archive_Tar 1.4.0 stable
Console_Getopt 1.4.1 stable
PEAR 1.10.1 stable
PEAR_Manpages 1.10.0 stable
Structures_Graph 1.1.1 stable
XML_Util 1.3.0 stable
$ pear install File_IMC
Failed to download pear/File_IMC within preferred state "stable", latest release is version 0.5.0, stability "beta", use "channel://pear.php.net/File_IMC-0.5.0" to install
install failed
$ pear install File_IMC-0.5.0 [Ret:1 16:11:41]
Cannot install, php_dir for channel "pear.php.net" is not writeable by the current user
$ sudo pear install File_IMC-0.5.0 [Ret:1 16:11:54]
downloading File_IMC-0.5.0.tgz ...
Starting to download File_IMC-0.5.0.tgz (32,161 bytes)
.....done: 32,161 bytes
install ok: channel://pear.php.net/File_IMC-0.5.0

以上でFile_IMCのインストールはおしまい。

 

使ってみる。

require_once('File/IMC.php');
$ical = file_get_contents('うんたらかんたら.ics');
$parse = File_IMC::parse('vCalendar');
$parse->fromText($ical);
$events = $parse->getEvents();

$data = array();
while ($events->valid()) {
$event = $events->current();
$data[] = array(
'start' => $event->getStart(),
'end' => $event->getEnd(),
'summary' => $event->getSummary(),
'description' => $event->getDescription()
);
$events->next();
}

print_r($data);

startの値でソートしたければ、

foreach((array) $data as $key => $value) {
$sort[$key] = $value['start'];
}
array_multisort($sort, SORT_ASC, $data);

 

あとはてきとうに整形するなりなんなりでいいんだけど…Googleカレンダーでは場所情報が記録できるのに、File_IMCにgetLocation()つーメソッドは無い。

見たとこイベント開始/終了時刻、タイトル(summary)、詳細(description)しか拾えないっぽいので強引になんとかしてやるぜ!

/usr/share/php/File/IMC/Parse/Vcalendar/Event.phpに各メソッドが記述されているので、これをそれらしく書き換えればなんとかなるのでは?

というわけで下記コードをてきとうに追加

public function getLocation()
{
return $this->data['LOCATION'][0]['value'][0][0];
}

あとは同じ感覚で$event->getLocation()とかすれば拾い出せるはず。

PHP欠片も勉強しないで触ってもなんとかなるもんだね(目的のプラグインが作れたので)

まーセキュリティは何も考えてないんですけど

Ubuntu16.04のApache2でHTTP/2する

あると思ったらなかったHTTP/2対応(?)

$ sudo a2enmod http2
ERROR: Module http2 does not exist!
$ ls /etc/apache2/mods-available/http2.load
ls: cannot access '/etc/apache2/mods-available/http2.load': No such file or directory

マジかよ。

 

ぐぐってきたら、mod_http2.soが無いらしいので自前でapache2ビルドしてやれ、という情報が。やってやるぜ!

 

参考サイト:

How To Set Up Apache with HTTP/2 Support on Ubuntu 16.04 – WebSetNet

Bug #1543572 “mod_http2 is not available under apache 2.4.18 / U…”:Bugs:apache2 package:Ubuntu

流れは、

1. ソースを拾えるようにリポジトリリストをいじる
2. ビルドに必要なパッケージをインストール
3. ビルドする
4. mod_http2.soをコピー
5. mods-availableに配置するべきloadファイルを作成する

参考サイトでは最初にlibnghttp2-devをインストールさせてるけど、ぶっちゃけようわからん(まがお)一応入れました

 

さて作業。

$ sudo apt-get install libnghttp2-dev
$ tail -n3 /etc/apt/sources.list
deb-src http://archive.ubuntu.com/ubuntu xenial main universe restricted multiverse
deb-src http://security.ubuntu.com/ubuntu xenial-security main universe restricted multiverse
deb-src http://archive.ubuntu.com/ubuntu xenial-updates main universe restricted multiverse
$ sudo apt-get update
$ cd ~
$ mkdir apache2 
$ cd apache2
$ apt-get source apache2
$ sudo apt-get build-dep apache2
$ cd apache2-2.4.18
$ fakeroot debian/rules binary

以上でビルドが完了するはず。あとはコピーして有効化してなんたらかんたら

$ sudo cp ~/apache2/apache2-2.4.18/debian/apache2-bin/usr/lib/apache2/modules/mod_http2.so /usr/lib/apache2/modules/
$ cat /etc/apache2/mods-available/http2.load
LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so

<ifModule http2_module>
LogLevel http2:info
</ifModule>
$ sudo a2enmod http2
$ cat /etc/apache2/sites-enabled/default-ssl.conf
<ifModule mod_ssl.c>
<VirtualHost _default_:443>
〜略〜
Protocols h2 http/1.1
〜略〜
$ sudo service apache2 restart

あとはDeveloper Toolsでプロトコル調べるとかなんとかして動作チェックしよう。

Let’s encryptでサラッとHTTPSする

もうそこかしこに情報あるだろうけど、手元で実験出来たので取り敢えず記録。

状況は、

・http://test.tea-soak.org:12345で運用中とする(ホストは192.168.0.5)
・http://tea-soak.org:80でも別サービスを運用中(ホストは192.168.0.4)

で、test.の方をHTTPSにする。各ドメインは同じグローバルIPアドレスを指しているが、ポート番号によって区別し、192.168.0.5に行くか192.168.0.4に行くかをルータで振り分けている。

 

ArchLinuxを使っているのでLet’s encrypt – ArchWikiの通りに。

$ sudo pacman -S certbot
$ certbot certonly --manual
The following error was encountered:
[Errno 13] Permission denied: '/var/log/letsencrypt/letsencrypt.log'
If running as non-root, set --config-dir, --work-dir, and --logs-dir to writeable paths.

面倒なのでroot(sudo)でやりなおす

$ sudo certbot certonly --manual
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):honyarara@honyahonya.com

Please read the Terms of Service at ...
(A)gree/(C)ancel: A

Would you be willing to share your email address...
(Y)es/(N)o: n

Please enter in your domain names(s) (comma and/or space separated)  (Enter 'c' to cancel):test.tea-soak.org
...
Make sure your web server displays the following content at http://test.tea-soak.org/.well-known/acme-challenge/LT6x2... before continuing:

LT6x2...k4.JenbAW...

If you don't have HTTP server configured, you can run the following command on the target server (as root):
...
Press Enter to Continue

(長くなってしまうので抜粋しまくっておいた)

Press Enter to Continueのところで止まるので、http://test.tea-soak.org/.well-known/acme-challenge/LT6x2…でアクセスできるようにファイルを配置する。具体的にはfollowing command on the target server以下に並んでいるコマンドを参考になんとかする。

ドメインの存在確認のacme-challenge(そういう意味だよね?)はhttp://test.tea-soak.org:80に行くと思われるので、つまり192.168.0.4にアクセスが飛んでしまう。今回は面倒なので192.168.0.4に所定のファイルを設置した。

うまくいくと、/etc/letsencrypt/live/test.tea-soak.org/以下に鍵と証明書が保存されるはず。

privkey.pem:証明書の秘密鍵
fullchain.pem:証明書(多くのサーバソフトで使えるらしい)

各ファイルの説明はREADMEに入っている(上記はてきとう和訳)

 

test.tea-soak.orgではnginxが動いているので設定をいじる。

大雑把に以下みたいな感じ

server {
listen 12345;
server_name test.tea-soak.org;
ssl on;
ssl_certificate /etc/letsencrypt/live/test.tea-soak.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test.tea-soak.org/privkey.pem;
]

あとはsudo systemctl restart nginxすると設定が有効になるはず

従来通りHTTPアクセスすると400 Bad Requestが返ってくるが、HTTPSではきちんとアクセスできることを確認しておしまい。

 

このやり方だと、証明書の更新は自動では出来ない。実験環境でなく本番環境で使うなら、こういうところの管理は自動化したいところだし、ArchWikiの下の方読もう()

SQLのデータベース操作(いつも忘れる)

使うけれど使うときにいつも忘れちゃうのでメモ。毎度ぐぐってくるの面倒なのだ

 

・データベースとそれ用ユーザをつくる

CREATE DATABASE database_name;
CREATE USER 'user_name'@'localhost' IDNETIFIED BY 'password';
GRANT ALL PRIVILEGES ON database_name.* TO 'user_name'@'localhost';
FLUSH PRIVILEGES;

・ユーザの一覧を見る

USE mysql;
SELECT user,host FROM user;

・テーブル、データベースを削除する

DROP TABLE table_name;
DROP DATABASE database_name;

 

distccでmakepkgの高速化を狙う

ビルドって結構時間かかる。最近telegram-desktop – aurがしょっちゅうバージョンアップするわけだが、これ、Qtのstatic版を手元で毎度ビルドするのだ。まぁそれを保持しておいてくれればいいんだけど、これの他にも色々ビルドすることはあるので、PKGBUILDからビルドしてくれるmakepkgを高速化してやりたい。

makeに手作業で-jとかつけて回っても良いが、せっかく手元にマシンが複数あるので、分散ビルドさせてみたほうが面白いのでは?つーわけで、distccをつかう。

 

基本的にはDistcc – ArchWikiの通りの作業でおk。

一応記しておこう。

 

状況は以下のとおり。

参加するホスト:マスター(192.168.0.55)、スレーブ(192.168.0.70)

マスターのCPU:Core i7 870(4C/8T)、スレーブのCPU:Celeron G550(2C/2T)

 

インストールはdistccパッケージを放り込めばおk、マスターにもスレーブにもインストールしよう。

 

スレーブの設定は/etc/conf.d/distccdを多少いじるのみ。

DISTCC_ARGS=”–allow 192.168.0.0/24″

の行をそれらしくしたら、systemctl start distccdすればおk

 

マスターでは/etc/makepkg.confをいじる。

・BUILDENVでdistccの前のビックリマークを切る

・DISTCC_HOSTSでジョブを実行するホストとそこのスレッド数を指定する(パワーが強い順にする)

・MAKEFLAGSで全スレッド数を合計したものを指定する

DISTCC_HOSTS=”localhost/8 192.168.0.70/2″
MAKEFLAGS=”-j10″

 

以上で設定はおしまい。パフォーマンス比較ということで、Linuxカーネルをビルドしてみよう。

$ cd
$ mkdir kernel_build &amp;amp;&amp;amp; cd kernel_build
$ ABSROOT=. abs core/linux
$ cd ./core./linux
$ vim PKGBUILD
$ makepkg
$ sudo pacman -S xmlto
$ time makepkg

鍵の検証が出来ないとかなんとか言われたので、ひとまず.signをなかったことにしておいた。

先にmakepkgを実行してやれば、必要なもので今入っていないパッケージがどれかわかる。というわけでxmltoだけ手動でインストールした。

最後は実際のビルドと計測である。

 

distcc有効/無効でtimeの出力は以下の通り

# distcc無効
makepkg 10837.49s user 692.22s system 695% cpu 27:37.28 total
# distcc有効
makepkg  8178.88s user 584.70s system 560% cpu 26:02.75 total

多少早くなっているみたい(認識が雑)

 

ビルド中の様子はdistccmon-{text,gnome}で確認できる。gnomeだと様子が視覚的に見えておもしろい。

telegram-desktopビルド中

 

我が家にあるCPUは以下の通り

・Pentium DualCore E5300(自宅サーバ、Ubuntu16.04)
・Celeron G550(今回スレーブで使ったクソショボCPU、ArchLinux)
・Core i7 870(旧メインマシン、諸々作業所、ArchLinux)
・Core i7 6700K(現メインマシン、Windows10)
・AthlonII X2 250e(録画機、Windows7)

自宅サーバは違うディストロなのでコンパイラバージョンが食い違っていることが予想される(上にパワーが死ぬほど無い)ので組み込みにくい。あとはWindowsなので組み込むのダルい…メインマシンをArchLinuxにしちゃおうか悩むくらいだ。

計画では、そろそろ自宅サーバを新調する予定なので、それを参加するようにできれば、それでいいかな…

systemd-nspawnでコンテナをブリッジ接続する

2017/02/18 /var/lib/machinesの所在についてを追記

 

systemd-nspawnが何かはsystemd-nspawn – ArchWikiを見ていただくとして。

 

systemd-nspawnはネットワークに関して何も指定せず起動すると、ホストと共通のネットワークになる。同じIPアドレスを持つ、みたいな感じ。特に何も考えなくて済むので楽と言えば楽だけど、コンテナを仮想マシンみたいな感覚で触ろうと思うと、なかなかキツい。sshのポート変えれば区別出来るけど、みたいな状況になってしまう。

-n(–network-veth)オプションをつけると、ホスト・コンテナ双方に仮想イーサネットインターフェイスを作成して、これを接続する。ホストの下に新たにネットワークを作るようなものなので、お隣のパソコンからコンテナにアクセスしようとすると、きちんとルーティングしたりIPマスカレードしたりとかしないといけないっぽい。(それで出来るかは未確認)

既存のLANにコンテナが参加出来れば、つまりホストを通してブリッジ接続出来れば、まさしく仮想的に新たなマシンを起こした感覚で操作出来る。これが一番従来通りの感覚で操作できて、お話が簡単なはずだ。

 

 

ネットワークは、
ホームルータ(ゲートウェイ、DNS):192.168.0.1
ホスト:192.168.0.3
コンテナ:192.168.0.10
ホストに接続されてるインターフェイス:enp6s0
という事にしてみよう。

 

参考サイト:

まとめて面倒見てくれる勢いのsystemd(隔離とネットワーク) – GeeksDev [archive]

systemd-nspawn – ArchWiki

systemd-networkd – ArchWiki

 

さて実際の操作。

まずコンテナをつくる。

$ sudo pacman -S arch-install-scripts
$ mkdir cont
$ sudo pacstrap -i -c -d ./cont base --ignore linux
$ sudo systemd-nspawn -bnD ./cont

最後は一応の動作チェック。root(パスワード無し)でログインする。

systemd-nspawnからログインした場合はいいけど、後でさわるmachinectlからloginしようとすると、Login incorrectで怒られる。で、journalctl -xe -M contみたいな感じで当該コンテナのメッセージを見て、access denied: tty ‘pts/0’ is not secure!みたいに書いてあったら、コンテナ内の/etc/securettyにpts/0を追加すればイケるはず。

問題なさそうならpoweroffで帰ってこよう。

次にmachinectlでいじれるようにする。このままだと、

$ machinectl start cont
Machine image 'cont' does not exist.

はい。所定の場所にmvします。machinectl image-statusあたりで調べられる。

$ machinectl image-status
Path: /var/lib/machines
$ sudo mv ./cont /var/lib/machines/cont
$ machinectl list-images
NAME TYPE      RO USAGE CREATED MODIFIED
cont directory no n/a   n/a     n/a
$ machinectl start cont
$ machinectl login cont

正しく起動出来てログイン出来ていればおk。systemctl status systemd-nspawn@contを見れば正常に起動しているのが見えてくるはず。

 

 

つぎ、仮想ブリッジをつくるぞ~。

ホスト、コンテナ両方で以下をやっておいて、余計な接続をしないようにしておく。

$ sudo ln -sf /dev/null /etc/systemd/network/80-container-host0.network

ホスト側:

$ cat /etc/systemd/network/br0.netdev
[NetDev]
Name=br0
Kind=bridge

$ cat /etc/systemd/network/br0.network
[Match]
Name=br0

[Network]
DNS=192.168.0.1
Address=192.168.0.3/24
Gateway=192.168.0.1

$ cat /etc/systemd/network/eth.network
[Match]
Name=enp6s0

[Network]
Bridge=br0

次にコンテナにブリッジbr0を利用するように設定する。よくわかんなかったのでsystemctl status systemd-nspawn@contしたら見えたファイルをいじったのであった。

$ cat /usr/lib/systemd/system/systemd-nspawn@.service | grep ExecStart
#ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=%i
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-bridge=br0 -U --settings=override --machine=%i

1行目はもとあったもので、–network-vethがついている。(コメントアウトした)

2行目は–network-vethを–network-bridge=br0に差し替えたもの。

 

最後にコンテナ内をいじる。

$ cat /etc/systemd/network/host0.network
[Match]
Name=host0

[Network]
DNS=192.168.0.1
Address=192.168.0.10/24
Gateway=192.168.0.1

最後に、てきとうにsystemd-networkdをstartしたりenableしたりしておく。

以上まででブリッジ接続出来ているはず。コンテナ、ホスト、お隣のパソコンの3者からお互いにアクセス出来る。

 

これで鯖を新調して仮想化ドヤァ出来るようになったぞ!あとはお金を貯めるだけだ(しろめ)

LAN内にいるIPアドレスを一覧したい nmap,arp-scan

DHCPで繋いだ時のIPアドレスがわからなくてこまる事がある。例えば何もいじってない状態の玄箱にtelnetしたいとか。そういえば玄箱全然いじってないな。

という訳でLANの中にいるIPアドレスを調べる。

nmapは-sPとか-PRとかつけて目的ネットワークを指定すればおk

sudoつけないと色々面倒なお話があるのだが、ネットワークのお話をちゃんと勉強しないとわからないっぽいので後日。(sudoつけなくても使えるが機能が制限される)

 

次、arp-scanは-I(–interface)でインターフェイスを指定して、-l(–localnet)オプション付ける

localnetオプションは検索対象をローカルの全てのアドレスにする。インターフェイスのアドレスが192.168.0.3/24とかだったりすると、192.168.0.0〜192.168.0.255を探索するようだ

こっちはそもそもsudoつけないと怒られる(パケットを読み書きするのにroot privilegeが必要)

 

$ nmap -sP 192.168.0.0/24
$ sudo nmap -PR 192.168.0.0/24  # ポートスキャンやってくれる
$ sudo arp-scan -I wlp2s0 -l

dnsmasqで内向きDNS

今更なネタではあるような気がするけど、dnsmasqで内向きDNSを立てた。

以前、ArchLinuxのリポジトリミラーをローカルに立てるという事で、ローカルにミラーを立てたのは良いけれど、家にいるときはローカルミラー、外にいるときは他のミラー…というように接続先を変えるのが面倒くさい。

実はネットワークに接続するたびに毎度毎度mirrorlistを手作業でいじっていたのだ。アホ。

これ自動化する手があるのかもしれないけど、それよりも、ドメイン登録して外からローカルミラーにアクセス出来るようにして、自宅からは内向きDNSで解決するようにして、mirrorlistにはいつも同じドメイン名書いておけばよいのでは?という結論にいたった。しょーもな。

という訳でそういうお話。

 

dnsmasqは/etc/hostsをもとに名前解決してくれるDNSサーバとして使う事が出来る(BINDみたいに面倒な設定書かずに済んで楽ちんなのだ)

 

 

やることをまとめると、

・それらしいドメイン名で自宅外から自宅内のマシンにアクセス出来る

・自宅内でも同じドメイン名でローカルマシンにアクセス出来る

 

今回は、repo.hoge.comを192.168.0.3とかにあててみようと思う。

 

まずはdnsmasqを導入する。

$ sudo pacman -S dnsmasq

何も考える必要ないっすね。で、設定をいじる。/etc/dnsmasq.confにいる。

domain-needed
bogus-priv
local=/hoge.com/
no-dhcp-interface=enp6s0
expand-hosts
domain=hoge.com

次、/etc/hosts

$ cat /etc/hosts
127.0.0.1 localhost.localdomain localhost
::1 localhost.localdomain localhost
192.168.0.3 repo.hoge.com

サーバの設定はおしまいなので起動設定(と起動)

$ sudo systemctl enable dnsmasq
$ sudo systemctl start dnsmasq

気になるようだったらサーバでrepo.hoge.comにpingとかしましょう

/etc/hostsを設定した時点でサーバ内では名前解決出来るけど、ローカルネットワークの他のマシンからは名前解決出来ない。DNSにサーバを指定すればともかく、それをしたら他のネットワークに参加した時にまた対応せにゃならんでしょう(プロファイル作ってわけるってのもあるけど、手作業が面倒なのが根本なのでなしの方向で)

つー訳で、ルータから特定ドメインの名前解決リクエストだけサーバに飛ばすように設定する(たぶん)。我が家のルータはAterm WR8370Nなので、他の機種他のメーカーは知りません(

設定Web→詳細設定→DNSルーティング設定にルーティングエントリとして追加する

宛先ドメイン:repo.hoge.com
ゲートウェイ:192.168.0.3
プライマリDNS:192.168.0.3

あとは設定を保存して動作チェックだ。

 

最終的な状況は、

自宅LAN外からアクセス→おなまえどっとこむのDNSを使って名前解決→通常のサーバのようにポートマッピングでサーバへ接続

自宅LAN内からアクセス→LAN内メインDNSサーバたるルータへ要求→ルータは設定されたドメインなので192.168.0.3へ転送→192.168.0.3のdnsmasqが解決してくれる

という感じかしら?

 

これ、別にリポジトリミラーの話に限る必要は無くて、自宅鯖とかに普通に使えるんすよね…

自宅にあるマシンはどれも手作業でhostsいじってたけど、これからはこれ使って楽ちん設定だー。

特定コマンドが含まれているパッケージを探す

ArchLinuxって最小限のインストール構成だと(最小限なので当然なんだけど)使いにくいレベルで何も入ってない。

そこから好きなもの、必要なものだけに絞ってインストールしていけるので、大変そういう意味では良いんだけど、まともに環境構築するつもりはなくて、とにかく実験環境とか遊び環境として一つ欲しいときに、「あのコマンドだけ欲しい」とかあるんすよ

最近研究室に新しいサーバ機が届きまして、早速諸々の構築をしていきたいんだけど、教授からは「Windows Serverにしような」と言われてしまい、しかしそのインストールメディアは先生が持っていて、更に言うとストレージも実は用意してないので、やっぱり何も出来ない状況なのだ…

とは言え、こんな格好のおもちゃ、放置しておくのは勿体無いよねって事で、USBメモリにOSをインストールしてそこから起動して色々遊べばいいじゃん〜と。

要はまともに環境構築する気が無い環境で、アレ欲しいコレ欲しいって単発で欲しくなったときに、具体的にどのパッケージをインストールすれば良いのかを探す。

 

今回欲しかったのはifconfig。NICの名前とかIPアドレスとか知りたいとふと思ったときに無意識に打ち込んじゃうけれど、これ最初は入ってないんでした……

pacmanにオプションQoをつけて目的バイナリを探してきてねってお願いすると、パッケージ名出してくれます。

 

$ which ifconfig
/usr/bin/ifconfig
$ pacman -Qo /usr/bin/ifconfig
/usr/bin/ifconfig は net-tools 1.60.20160710git-1 によって保有されています

2行にわたったり入力したりめんどいので以下みたいなノリで短縮も可

$ which ifconfig | pacman -Qo -

aliasなコマンド(lsなんかはls –color=autoになっている場合をよく見る)の場合には一度unaliasする以外方法見つかりませんでした(まがお)

関数の引数として関数をとる

C++なら関数オブジェクト使えとかいう記述をどこかで見かけたんだけど、結局よくわからなかったので関数ポインタを使う事にした。

引数の型 (*関数ポインタ名)(その関数がとる引数の型)

という形で宣言して使う。

例えばintで1つ引数をとって、5足したものを返してくれる関数を考えてみる。

int calc(int in){
return in+5;
}

int main(){
int (*fp)(int);
fp = calc;
fp(2)    // 7が返ってくる
return 0;
}

細かいアレはともかくとして、fpが関数ポインタ。こういう使い方だと今のとこあんま面白くないけど、関数ポインタを使えば関数の引数に関数を使える。

与えられた関数から返ってきた値の正負を判定する関数pmを考える。

int calc(int in){
return in+5;
}

bool pm(int (*fp)(int), int in){
if(fp(in)<0){
return false;
}else{
return true;
}
}

int main(){
pm(calc, -6)    //false
pm(calc, 3)    //true
return 0;
}

使いどころは、計算の一部分を利用者から与えてもらって、それを使って全体の計算をやるって場面。(ていうかそういう場面があったのでこうやって書きました)

具体的に言うと、数値解析のときにつかうテクニックがあるんだけど、これを毎度書いてるとウザいので、オレオレライブラリにしてやろうという感じ。テクニックのアルゴリズム自体はライブラリ側で全部書いておいて、利用者は目的関数の定義だけしてあとはそれを放り込むだけ〜というやつ。

ぶっちゃけこういう内容1年くらい前にやるべきみたいな雰囲気はある(今年度何した?に答えたくない)