|
From: Shiro K. <sh...@la...> - 2009-04-23 01:20:09
|
From: Lasse Kliemann <las...@ma...>
Subject: [Gauche-devel] pipe chain
Date: Wed, 22 Apr 2009 23:13:17 +0200
> How can I connect serveral sub-processes by pipes, like in shell
> I do with 'cmd1 | cmd2 | cmd3' ?
This feature has been sitting on the TODO list for long long time.
Implementing it won't be very difficult, but coming up a right
API isn't trivial if we want flexibility more than a simple pipeline.
Scsh has very thorough support on process control but I'm a bit
uncomfortable with its syntax.
So, at this moment, the easiest way is to delegate the task to
the shell:
(run-process "cmd1 | cmd2 | cmd3" ...)
A major drawback is that, when commands and their arguments are
given from outside, you have to be very careful quoting them
correctly.
If you want just a simple straight pipe, you can write something
like this:
===============================================
(use gauche.process)
(use gauche.sequence)
(use util.list)
(define (run-simple-pipe cmd . cmds)
(let* ([pipes (fold (lambda (p s)
(receive (in out) (sys-pipe :buffering :none)
(list* in out s)))
'(#f) cmds)]
[pids (map (lambda (cmd io)
(sys-fork-and-exec
(x->string (car cmd)) (map x->string cmd)
:iomap (cond-list [(car io) => (cut cons 0 <>)]
[(cadr io) => (cut cons 1 <>)]
[#t '(2 . 2)])))
(cons cmd cmds) (slices (reverse pipes) 2 #t 1))])
(dolist [p pipes] (cond [(input-port? p) (close-input-port p)]
[(output-port? p) (close-output-port p)]))
(for-each sys-waitpid pids)
(values)))
================================================
Example:
gosh> (run-simple-pipe '(ls -l) '(grep ".*\\.[ch]") '(wc))
65 585 3606
--shiro
|