Re: Struggling in making a sub-process work in an interactive way

2012-01-13 Thread Denis Labaye
I replied a bit too fast, I didn't realized you wanted to such an advanced
thing

It is probably more a JVM question than a Clojure question then.

On Fri, Jan 13, 2012 at 3:42 AM, jaime xiejianm...@gmail.com wrote:

 Well actually I also tried commons-exec but it's the same as
 clojure.java.shell - they run system command directly, after execution
 they return and terminate. That's not the way I want

 On Jan 13, 2:42 am, Denis Labaye denis.lab...@gmail.com wrote:
  Hi,
 
  In Java you would do it with common-exec:http://commons.apache.org/exec/
 
  So add the deps to your project.clj :
 
  :dependencies [[org.apache.commons/commons-exec 1.1]]
 
  And use Clojure's Java interop.
 
  Keep us posted, I will need to do the same thing soon :)
 
  Denis
 
 
 
 
 
 
 
  On Wed, Jan 11, 2012 at 4:05 AM, jaime xiejianm...@gmail.com wrote:
   I didn't read your code carefully yet but I think you're meaning to
   copy streams between my Clojure code and the sub-process, actually
   I've tried this but this is probably not what I want.
   I might not make myself clear. So here I go again:
1. I writing a program which will open an OS shell (that means cmd
   under Windows and bash under Linux) as sub-process
2. this shell thing will not terminate while my code is still
   running, all system commands such as dir/ls/cat etc. will be thrown
   into the shell's input-stream to execute and the result is pulled
   from shell's output-stream/err-stream
3. because when the shell will finish its execution is
   unpredictable, I chained an echo stop-sign command to original
   command so that the program can get the sign when execution done. E.g.
   for command dir, I will throw dir echo stop-sign to the shell,
   when a stop-sign is captured then it knows the execution finished
4. it works well so far but when the system command is interactive
   one such as 'time' (in Windows), the program will hang; if there are
   ways to know when to require user input then I can resolve this in the
   code, but the answer is NO. I didn't find a way to detect this
5. thus I tried to find out any workarounds but failed. I also tried
   the way you mentioned here, it can work in an interactive way but in
   this case I cannot get the control back.
 
   That's all the things I'm struggling on...
 
   On Jan 10, 4:54 pm, Alan Malloy a...@malloys.org wrote:
On Jan 9, 9:24 pm, Phil Hagelberg p...@hagelb.org wrote:
 
 jaime xiejianm...@gmail.com writes:
  Later on I tried to add code that can make this possible but I
 found
  there's no way to detect if a command requires user's input and
 thus
   I
  have to find another way to make it work - but I didn't success
 and
  have been struggling for a workaround for a long while
 
  anyone has any idea?
 
 As far as I know this is impossible to do without bringing in
 third-party libraries; this is just a (rather serious) shortcoming
 of
 the JDK. I haven't looked into it enough to know which libraries
 would
 offer it though.
 
This should be possible if you don't mind suiciding your own
 process's
stdin/stdout, by blindly forwarding all your input and output through
the child. But if you send the child some input it didn't need, and
 it
terminates, and then later you need your own stdin again, some pieces
will be missing.
 
I was going to attach a simple proof of concept to this, but I can't
seem to get it right. So instead, here's what I was trying to do, and
if someone wants to take it up this might be something useful to work
from:
 
(ns fork.core
  (:require [clojure.java.io :as io])
  (:import (java.io PipedReader PipedWriter))
  (:gen-class))
 
(defn -main [ args]
  (println Start typing, I'll cat it back atcha!)
  (let [child (- (Runtime/getRuntime) (.exec /bin/cat))
cin (.getInputStream child)
cout (.getOutputStream child)
 
in-pipe-in (PipedReader.)
in-pipe-out (PipedWriter. in-pipe-in)
 
out-pipe-in (PipedReader.)
out-pipe-out (PipedWriter. out-pipe-in)
 
in *in*, out *out*] ;; avoid dynamic-binding issues
(future (io/copy in in-pipe-out)) ;; read my stdin...
(future (io/copy in-pipe-in cout)) ;; write it to child's stdin
 
(future (io/copy cin out-pipe-out)) ;; read child's stdout...
@(future (io/copy out-pipe-in out)) ;; write it to my stdout, and
wait for it to finish
(let [exit-code (.waitFor child)]
  (println Child process finished with exit code exit-code)
  exit-code)))
 
   --
   You received this message because you are subscribed to the Google
   Groups Clojure group.
   To post to this group, send email to clojure@googlegroups.com
   Note that posts from new members are moderated - please be patient with
   your first post.
   To unsubscribe from this group, send email to
   

Re: Struggling in making a sub-process work in an interactive way

2012-01-12 Thread Denis Labaye
Hi,

In Java you would do it with common-exec: http://commons.apache.org/exec/

So add the deps to your project.clj :

:dependencies [[org.apache.commons/commons-exec 1.1]]

And use Clojure's Java interop.

Keep us posted, I will need to do the same thing soon :)

Denis

On Wed, Jan 11, 2012 at 4:05 AM, jaime xiejianm...@gmail.com wrote:

 I didn't read your code carefully yet but I think you're meaning to
 copy streams between my Clojure code and the sub-process, actually
 I've tried this but this is probably not what I want.
 I might not make myself clear. So here I go again:
  1. I writing a program which will open an OS shell (that means cmd
 under Windows and bash under Linux) as sub-process
  2. this shell thing will not terminate while my code is still
 running, all system commands such as dir/ls/cat etc. will be thrown
 into the shell's input-stream to execute and the result is pulled
 from shell's output-stream/err-stream
  3. because when the shell will finish its execution is
 unpredictable, I chained an echo stop-sign command to original
 command so that the program can get the sign when execution done. E.g.
 for command dir, I will throw dir echo stop-sign to the shell,
 when a stop-sign is captured then it knows the execution finished
  4. it works well so far but when the system command is interactive
 one such as 'time' (in Windows), the program will hang; if there are
 ways to know when to require user input then I can resolve this in the
 code, but the answer is NO. I didn't find a way to detect this
  5. thus I tried to find out any workarounds but failed. I also tried
 the way you mentioned here, it can work in an interactive way but in
 this case I cannot get the control back.

 That's all the things I'm struggling on...

 On Jan 10, 4:54 pm, Alan Malloy a...@malloys.org wrote:
  On Jan 9, 9:24 pm, Phil Hagelberg p...@hagelb.org wrote:
 
   jaime xiejianm...@gmail.com writes:
Later on I tried to add code that can make this possible but I found
there's no way to detect if a command requires user's input and thus
 I
have to find another way to make it work - but I didn't success and
have been struggling for a workaround for a long while
 
anyone has any idea?
 
   As far as I know this is impossible to do without bringing in
   third-party libraries; this is just a (rather serious) shortcoming of
   the JDK. I haven't looked into it enough to know which libraries would
   offer it though.
 
  This should be possible if you don't mind suiciding your own process's
  stdin/stdout, by blindly forwarding all your input and output through
  the child. But if you send the child some input it didn't need, and it
  terminates, and then later you need your own stdin again, some pieces
  will be missing.
 
  I was going to attach a simple proof of concept to this, but I can't
  seem to get it right. So instead, here's what I was trying to do, and
  if someone wants to take it up this might be something useful to work
  from:
 
  (ns fork.core
(:require [clojure.java.io :as io])
(:import (java.io PipedReader PipedWriter))
(:gen-class))
 
  (defn -main [ args]
(println Start typing, I'll cat it back atcha!)
(let [child (- (Runtime/getRuntime) (.exec /bin/cat))
  cin (.getInputStream child)
  cout (.getOutputStream child)
 
  in-pipe-in (PipedReader.)
  in-pipe-out (PipedWriter. in-pipe-in)
 
  out-pipe-in (PipedReader.)
  out-pipe-out (PipedWriter. out-pipe-in)
 
  in *in*, out *out*] ;; avoid dynamic-binding issues
  (future (io/copy in in-pipe-out)) ;; read my stdin...
  (future (io/copy in-pipe-in cout)) ;; write it to child's stdin
 
  (future (io/copy cin out-pipe-out)) ;; read child's stdout...
  @(future (io/copy out-pipe-in out)) ;; write it to my stdout, and
  wait for it to finish
  (let [exit-code (.waitFor child)]
(println Child process finished with exit code exit-code)
exit-code)))

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Struggling in making a sub-process work in an interactive way

2012-01-12 Thread jaime
Well actually I also tried commons-exec but it's the same as
clojure.java.shell - they run system command directly, after execution
they return and terminate. That's not the way I want

On Jan 13, 2:42 am, Denis Labaye denis.lab...@gmail.com wrote:
 Hi,

 In Java you would do it with common-exec:http://commons.apache.org/exec/

 So add the deps to your project.clj :

 :dependencies [[org.apache.commons/commons-exec 1.1]]

 And use Clojure's Java interop.

 Keep us posted, I will need to do the same thing soon :)

 Denis







 On Wed, Jan 11, 2012 at 4:05 AM, jaime xiejianm...@gmail.com wrote:
  I didn't read your code carefully yet but I think you're meaning to
  copy streams between my Clojure code and the sub-process, actually
  I've tried this but this is probably not what I want.
  I might not make myself clear. So here I go again:
   1. I writing a program which will open an OS shell (that means cmd
  under Windows and bash under Linux) as sub-process
   2. this shell thing will not terminate while my code is still
  running, all system commands such as dir/ls/cat etc. will be thrown
  into     the shell's input-stream to execute and the result is pulled
  from shell's output-stream/err-stream
   3. because when the shell will finish its execution is
  unpredictable, I chained an echo stop-sign command to original
  command so that the program can get the sign when execution done. E.g.
  for command dir, I will throw dir echo stop-sign to the shell,
  when a stop-sign is captured then it knows the execution finished
   4. it works well so far but when the system command is interactive
  one such as 'time' (in Windows), the program will hang; if there are
  ways to know when to require user input then I can resolve this in the
  code, but the answer is NO. I didn't find a way to detect this
   5. thus I tried to find out any workarounds but failed. I also tried
  the way you mentioned here, it can work in an interactive way but in
  this case I cannot get the control back.

  That's all the things I'm struggling on...

  On Jan 10, 4:54 pm, Alan Malloy a...@malloys.org wrote:
   On Jan 9, 9:24 pm, Phil Hagelberg p...@hagelb.org wrote:

jaime xiejianm...@gmail.com writes:
 Later on I tried to add code that can make this possible but I found
 there's no way to detect if a command requires user's input and thus
  I
 have to find another way to make it work - but I didn't success and
 have been struggling for a workaround for a long while

 anyone has any idea?

As far as I know this is impossible to do without bringing in
third-party libraries; this is just a (rather serious) shortcoming of
the JDK. I haven't looked into it enough to know which libraries would
offer it though.

   This should be possible if you don't mind suiciding your own process's
   stdin/stdout, by blindly forwarding all your input and output through
   the child. But if you send the child some input it didn't need, and it
   terminates, and then later you need your own stdin again, some pieces
   will be missing.

   I was going to attach a simple proof of concept to this, but I can't
   seem to get it right. So instead, here's what I was trying to do, and
   if someone wants to take it up this might be something useful to work
   from:

   (ns fork.core
     (:require [clojure.java.io :as io])
     (:import (java.io PipedReader PipedWriter))
     (:gen-class))

   (defn -main [ args]
     (println Start typing, I'll cat it back atcha!)
     (let [child (- (Runtime/getRuntime) (.exec /bin/cat))
           cin (.getInputStream child)
           cout (.getOutputStream child)

           in-pipe-in (PipedReader.)
           in-pipe-out (PipedWriter. in-pipe-in)

           out-pipe-in (PipedReader.)
           out-pipe-out (PipedWriter. out-pipe-in)

           in *in*, out *out*] ;; avoid dynamic-binding issues
       (future (io/copy in in-pipe-out)) ;; read my stdin...
       (future (io/copy in-pipe-in cout)) ;; write it to child's stdin

       (future (io/copy cin out-pipe-out)) ;; read child's stdout...
       @(future (io/copy out-pipe-in out)) ;; write it to my stdout, and
   wait for it to finish
       (let [exit-code (.waitFor child)]
         (println Child process finished with exit code exit-code)
         exit-code)))

  --
  You received this message because you are subscribed to the Google
  Groups Clojure group.
  To post to this group, send email to clojure@googlegroups.com
  Note that posts from new members are moderated - please be patient with
  your first post.
  To unsubscribe from this group, send email to
  clojure+unsubscr...@googlegroups.com
  For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 

Re: Struggling in making a sub-process work in an interactive way

2012-01-10 Thread Alan Malloy
On Jan 9, 9:24 pm, Phil Hagelberg p...@hagelb.org wrote:
 jaime xiejianm...@gmail.com writes:
  Later on I tried to add code that can make this possible but I found
  there's no way to detect if a command requires user's input and thus I
  have to find another way to make it work - but I didn't success and
  have been struggling for a workaround for a long while

  anyone has any idea?

 As far as I know this is impossible to do without bringing in
 third-party libraries; this is just a (rather serious) shortcoming of
 the JDK. I haven't looked into it enough to know which libraries would
 offer it though.

This should be possible if you don't mind suiciding your own process's
stdin/stdout, by blindly forwarding all your input and output through
the child. But if you send the child some input it didn't need, and it
terminates, and then later you need your own stdin again, some pieces
will be missing.

I was going to attach a simple proof of concept to this, but I can't
seem to get it right. So instead, here's what I was trying to do, and
if someone wants to take it up this might be something useful to work
from:

(ns fork.core
  (:require [clojure.java.io :as io])
  (:import (java.io PipedReader PipedWriter))
  (:gen-class))

(defn -main [ args]
  (println Start typing, I'll cat it back atcha!)
  (let [child (- (Runtime/getRuntime) (.exec /bin/cat))
cin (.getInputStream child)
cout (.getOutputStream child)

in-pipe-in (PipedReader.)
in-pipe-out (PipedWriter. in-pipe-in)

out-pipe-in (PipedReader.)
out-pipe-out (PipedWriter. out-pipe-in)

in *in*, out *out*] ;; avoid dynamic-binding issues
(future (io/copy in in-pipe-out)) ;; read my stdin...
(future (io/copy in-pipe-in cout)) ;; write it to child's stdin

(future (io/copy cin out-pipe-out)) ;; read child's stdout...
@(future (io/copy out-pipe-in out)) ;; write it to my stdout, and
wait for it to finish
(let [exit-code (.waitFor child)]
  (println Child process finished with exit code exit-code)
  exit-code)))

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Struggling in making a sub-process work in an interactive way

2012-01-10 Thread Phil Hagelberg
Alan Malloy a...@malloys.org writes:

 On Jan 9, 9:24 pm, Phil Hagelberg p...@hagelb.org wrote:
 As far as I know this is impossible to do without bringing in
 third-party libraries; this is just a (rather serious) shortcoming of
 the JDK. I haven't looked into it enough to know which libraries would
 offer it though.

 This should be possible if you don't mind suiciding your own process's
 stdin/stdout, by blindly forwarding all your input and output through
 the child. But if you send the child some input it didn't need, and it
 terminates, and then later you need your own stdin again, some pieces
 will be missing.

Oops; that's right. What I should have said was that it's a shortcoming
of clojure.java.shell.

-Phil

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Struggling in making a sub-process work in an interactive way

2012-01-10 Thread Ryan Waters
On Mon, Jan 9, 2012 at 11:20 PM, jaime xiejianm...@gmail.com wrote:

 now it works fine for NON-interactive command such as dir or help,
 but it will hang when I send the shell commands that require user
 input, such as time. I think the reason is that my code doesn't
 detect any input requirement so the shell keep waiting for an input
 infinitely.


You could get around the blocking I/O problem with
java.nio.channels.Selector and the like.  Wrapping or duplicating what
expect4j does would do the trick.

http://code.google.com/p/expect4j/

- Ryan

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Struggling in making a sub-process work in an interactive way

2012-01-10 Thread jaime
I didn't read your code carefully yet but I think you're meaning to
copy streams between my Clojure code and the sub-process, actually
I've tried this but this is probably not what I want.
I might not make myself clear. So here I go again:
  1. I writing a program which will open an OS shell (that means cmd
under Windows and bash under Linux) as sub-process
  2. this shell thing will not terminate while my code is still
running, all system commands such as dir/ls/cat etc. will be thrown
into the shell's input-stream to execute and the result is pulled
from shell's output-stream/err-stream
  3. because when the shell will finish its execution is
unpredictable, I chained an echo stop-sign command to original
command so that the program can get the sign when execution done. E.g.
for command dir, I will throw dir echo stop-sign to the shell,
when a stop-sign is captured then it knows the execution finished
  4. it works well so far but when the system command is interactive
one such as 'time' (in Windows), the program will hang; if there are
ways to know when to require user input then I can resolve this in the
code, but the answer is NO. I didn't find a way to detect this
  5. thus I tried to find out any workarounds but failed. I also tried
the way you mentioned here, it can work in an interactive way but in
this case I cannot get the control back.

That's all the things I'm struggling on...

On Jan 10, 4:54 pm, Alan Malloy a...@malloys.org wrote:
 On Jan 9, 9:24 pm, Phil Hagelberg p...@hagelb.org wrote:

  jaime xiejianm...@gmail.com writes:
   Later on I tried to add code that can make this possible but I found
   there's no way to detect if a command requires user's input and thus I
   have to find another way to make it work - but I didn't success and
   have been struggling for a workaround for a long while

   anyone has any idea?

  As far as I know this is impossible to do without bringing in
  third-party libraries; this is just a (rather serious) shortcoming of
  the JDK. I haven't looked into it enough to know which libraries would
  offer it though.

 This should be possible if you don't mind suiciding your own process's
 stdin/stdout, by blindly forwarding all your input and output through
 the child. But if you send the child some input it didn't need, and it
 terminates, and then later you need your own stdin again, some pieces
 will be missing.

 I was going to attach a simple proof of concept to this, but I can't
 seem to get it right. So instead, here's what I was trying to do, and
 if someone wants to take it up this might be something useful to work
 from:

 (ns fork.core
   (:require [clojure.java.io :as io])
   (:import (java.io PipedReader PipedWriter))
   (:gen-class))

 (defn -main [ args]
   (println Start typing, I'll cat it back atcha!)
   (let [child (- (Runtime/getRuntime) (.exec /bin/cat))
         cin (.getInputStream child)
         cout (.getOutputStream child)

         in-pipe-in (PipedReader.)
         in-pipe-out (PipedWriter. in-pipe-in)

         out-pipe-in (PipedReader.)
         out-pipe-out (PipedWriter. out-pipe-in)

         in *in*, out *out*] ;; avoid dynamic-binding issues
     (future (io/copy in in-pipe-out)) ;; read my stdin...
     (future (io/copy in-pipe-in cout)) ;; write it to child's stdin

     (future (io/copy cin out-pipe-out)) ;; read child's stdout...
     @(future (io/copy out-pipe-in out)) ;; write it to my stdout, and
 wait for it to finish
     (let [exit-code (.waitFor child)]
       (println Child process finished with exit code exit-code)
       exit-code)))

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Struggling in making a sub-process work in an interactive way

2012-01-09 Thread jaime
Hello there,

I'm writing some code, int my code it does following things (under
Windows):
1. create a sub-process by (.exec (Runtime/getRuntime) cmd) named
shell
2. get input-stream, output-stream and err-stream from the shell
object
3. send commands to shell by dropping line into the output-string
then get any result from input-stream/err-stream

now it works fine for NON-interactive command such as dir or help,
but it will hang when I send the shell commands that require user
input, such as time. I think the reason is that my code doesn't
detect any input requirement so the shell keep waiting for an input
infinitely.

Later on I tried to add code that can make this possible but I found
there's no way to detect if a command requires user's input and thus I
have to find another way to make it work - but I didn't success and
have been struggling for a workaround for a long while

anyone has any idea?

Thanks,
Jaime

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Struggling in making a sub-process work in an interactive way

2012-01-09 Thread Phil Hagelberg
jaime xiejianm...@gmail.com writes:

 Later on I tried to add code that can make this possible but I found
 there's no way to detect if a command requires user's input and thus I
 have to find another way to make it work - but I didn't success and
 have been struggling for a workaround for a long while

 anyone has any idea?

As far as I know this is impossible to do without bringing in
third-party libraries; this is just a (rather serious) shortcoming of
the JDK. I haven't looked into it enough to know which libraries would
offer it though.

-Phil

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en