Windows 版 MzScheme から Cygwin のプログラムを動かす

タイトルの通りです。既存のライブラリそのままでは出来なかったので関数を作りました。

(require (lib "process.ss"))

(define shell (find-executable-path "sh.exe" #f))

(define (concat l)
  (apply string-append
         (cons (car l)
               (map (lambda (s)
                      (format " ~a" s))
                    (cdr l)))))

(define (system/cygwin exe . args)
  (let ((o (open-output-bytes)))
    (parameterize ((current-output-port o))
      (system* shell "-c" (concat (cons exe args)))
      (open-input-bytes (get-output-bytes o)))))

system/cygwin という名前で、プログラムの標準出力を入力ポートとして返します。

こんな風に使います。

(let ((in (system/cygwin
           "curl" "-X POST"
           (format "--basic --user ~a:~a" user pass)
           (format "-F \"photo=@~a\"" pathname-to-upload)
           (format "-F \"album_id=~a\"" album-id)
           "--url http://api.photozou.jp/rest/photo_add")))
  (ssax:xml->sxml in '()))


追記:

Cygwin のプログラムでも、シェルを経由せず直接

(system* exe 'exact (concat args))

のようにして実行できるみたいです。sh の起動負荷が無い分こっちの方が良いかもしれません。

この場合、exe はフルパスで指定するか、拡張子付きのファイル名のみで

(find-executable-path exe #f)

として検索することもできます。

なお、ライブラリ関数 system* を使うべき理由は、そうしないと出力ポートが詰まって MzScheme のプロセス自体がハングする場合があるためです。