とりあえず、直にcalコマンドを実行する方向は無しで頑張ってみました。
cal.php
<?=str_pad(($d=new DateTime)->setDate($argv[2]??$d->format('Y'),$argv[1]??$d->format('m'),1)->format('F Y'),20,' ',2)."\nSu Mo Tu We Th Fr Sa\n".preg_replace('/(.{1,21})/',"$1\n",str_repeat(' ',$d->format('w')).sprintf(str_repeat('%2d ',$d->format('t')),...range(1,31)));
$ php cal.php
July 2020
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
$ php cal.php 2
February 2020
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
$ php cal.php 2 1999
February 1999
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28
まとめて1年分表示など色々再現できていませんが…
2020/7/25 追記
ちょっと長めですが、当日ハイライト表示対応版
cal.php
<?=str_pad($a=($d=new DateTime)->setDate([[$j,$b,$y,$m]=explode(',',$d->format('j,F Y,Y,m')),$argv[2]??$y][1],$argv[1]??$m,1)->format('F Y'),20,' ',2)."\nSu Mo Tu We Th Fr Sa\n".preg_replace("/(^|\D)( ?$j)(\D)/",$b==$a?"$1\e[7m$2\e[m$3":"$0",preg_replace('/(.{1,21})/',"$1\n",str_repeat(' ',$d->format('w')).sprintf(str_repeat('%2d ',$d->format('t')),...range(1,31))));