Loading ...
Sorry, an error occurred while loading the content.

Invoke a command with a few lines input

Expand Messages
  • code17
    Hi, there I have the following problem: I want to invoke a interactive program from my ocaml source code and then sent a few lines to this slaver process from
    Message 1 of 4 , Nov 28, 2005
    • 0 Attachment
      Hi, there

      I have the following problem: I want to invoke a interactive program from
      my ocaml source code and then sent a few lines to this slaver process
      from its stdin. Moreover, I don't need anything about concurrency, the
      master program (the invoker) can be blocked or simply substituted by the
      slaver.

      If without the few lines, either Sys.command or Unix.execvp can satisfy
      this verbosely. However, neither of them will give the fd of the
      slaver's stdin. I read an example in the oreilly book
      (http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora168.html#toc252)
      which makes use of Unix.open_process, however this involves the master
      process interpreting all the input/output for the slaver, since the
      slaver is an interactive program.

      More accurately, I needs to do the following things, maybe you can suggest
      some solution from alternative ways:

      1) to invoke, in my main program, a ocaml toplevel with variable commands
      (e.g. ocaml -I +threads -I /usr/local/xxx xxx.cmo xxx.cma ...); and
      then send something like "open AAA;;\n open BBB;;\n" to the toplevel;
      and then there is nothing left for the main program to do, it's simply a
      interactive toplevel left. I know about the ocamlmktop utility, but the
      toplevel arguments/open-modules here are not fixed and vary from case
      to case, and I don't want to produce a temporary toplevel each time
      and then invoke it.

      2) similar thing for ocamlc compiler. I want to write a program which
      invoke ocamlc with varies arguments on a user program whose name is
      passed in as argument, besides I have to attach varies "open XXX" to
      the head of user program implicitly. Since ocamlc is not an
      interactive process, the problem this time is how to attach the few
      lines to the user program without having to write a temporary file,
      something like "cat" files and "pipe" to ocamlc.

      It there any standard (conventional) way in ocaml for doing these?

      Thanks in advance.

      code17
    • Richard Jones
      ... Unix.open_process_out will do this. However ... ... To do this as you specified, you d need to use the expect command, or else deal with the hassle of
      Message 2 of 4 , Nov 29, 2005
      • 0 Attachment
        On Tue, Nov 29, 2005 at 12:59:53AM +0100, code17 wrote:
        > I have the following problem: I want to invoke a interactive program from
        > my ocaml source code and then sent a few lines to this slaver process
        > from its stdin. Moreover, I don't need anything about concurrency, the
        > master program (the invoker) can be blocked or simply substituted by the
        > slaver.

        Unix.open_process_out will do this. However ...

        > 1) to invoke, in my main program, a ocaml toplevel with variable commands
        > (e.g. ocaml -I +threads -I /usr/local/xxx xxx.cmo xxx.cma ...); and
        > then send something like "open AAA;;\n open BBB;;\n" to the toplevel;
        > and then there is nothing left for the main program to do, it's simply a
        > interactive toplevel left. I know about the ocamlmktop utility, but the
        > toplevel arguments/open-modules here are not fixed and vary from case
        > to case, and I don't want to produce a temporary toplevel each time
        > and then invoke it.

        To do this as you specified, you'd need to use the 'expect' command,
        or else deal with the hassle of opening and managing a pty. I doubt
        it's even possible under Windows.

        ocamlmktop doesn't let you specify what modules to 'open'.
        Nevertheless it's possible to execute some "start of day" code by
        having a file called '.ocamlinit'. I do this in my interactive
        Adwords API tool -- the '.ocamlinit' file just contains a list of
        'open...' directives. The drawback is that the '.ocamlinit' file must
        be in the current directory (so the user must 'cd' to a particular
        directory before invoking your custom toplevel).

        > 2) similar thing for ocamlc compiler. I want to write a program which
        > invoke ocamlc with varies arguments on a user program whose name is
        > passed in as argument, besides I have to attach varies "open XXX" to
        > the head of user program implicitly. Since ocamlc is not an
        > interactive process, the problem this time is how to attach the few
        > lines to the user program without having to write a temporary file,
        > something like "cat" files and "pipe" to ocamlc.

        Sounds like a job for a wrapper script which invokes the preprocessor
        (ocamlc -pp ...)

        Rich.

        --
        Richard Jones, CTO Merjis Ltd.
        Merjis - web marketing and technology - http://merjis.com
        Team Notepad - intranets and extranets for business - http://team-notepad.com
      • code17
        Hi, Jones, thanks for the reply! Finally, I still have to use the open_process_out like function and work in an interpreting manner. At the end of this mail,
        Message 3 of 4 , Nov 29, 2005
        • 0 Attachment
          Hi, Jones, thanks for the reply!

          Finally, I still have to use the "open_process_out" like function and
          work in an interpreting manner. At the end of this mail, I attach a
          simplified version, wish it helpful for those having the same problem
          (My actual version is using create_process function to have better
          control with pid and interpret both input and output)

          The awkward thing of this solution is that now you'll have two processes
          running concurrently for this simplest task, one for stdin/stdout
          interface, the other behind is the real evaluator. All of these is just
          because I want to add a few lines to the toplevel at the beginning.

          I suspect whether there exist solutions to the following problems in
          ocaml (or even unix). If either of them has a answer, the number of
          running process can be reduced to one.

          1) Consider a process's default stdin as one end of a Unix.pipe, then
          the other end should be some system functionality taking keyboard
          input and write it into the pipe. The problem is that is it possible
          to get the file descriptor of that end? so that on plus of the
          standard key input, we can also manually sent input to the stdin of a
          process.

          2) Is is possible to create a pipe with two input file descriptors and
          one output file descriptor? or maybe such a 3-end pipe is against the
          unix philosophy and doesn't exist in *nix system? (Some utility
          called "tee" seems be able to do this, however it is an application
          not a system primitive. And it probably works just in the same way as
          my simple interpreter functions does, since you also have a extra
          "tee" process during the whole life period of your pipe)


          ps. .ocamlinit doesn't work for my case, as the open modules vary from
          case to case according to some user arguments.

          pps. About the ocamlc problem, I think your suggestion of using
          preprocessor is the definitive answer. The camlp4 should be the choice,
          since my program works as soon as there exists a ocaml compiler in the
          system, so we can only assure the existence of camlp4. Since I don't
          know anything about camlp4, can anybody drop me a line on how to do this
          simplest job --- to attach a extra line to the head of input file? To
          seek for the answer to a simplest problem in a long long manual is
          rather a boring task :-(

          - code17


          (* Example code begins here *)

          let mainloop c_out =
          while
          (try let p,_ = Unix.waitpid [Unix.WNOHANG] (-1) in (p = 0)
          with _ -> false)
          do
          let s = read_line () in
          output_string c_out (s^"\n");
          flush c_out;
          done;;

          let c_out = Unix.open_process_out "ocaml";;
          let openmode = "open List;;\n";;

          output_string c_out openmode; flush c_out;;
          mainloop c_out;;

          (* Example code ends here *)


          Richard Jones <rich@...> writes:
          > Unix.open_process_out will do this. However ...
          > To do this as you specified, you'd need to use the 'expect' command,
          > or else deal with the hassle of opening and managing a pty. I doubt
          > it's even possible under Windows.
          >
          > ocamlmktop doesn't let you specify what modules to 'open'.
          > Nevertheless it's possible to execute some "start of day" code by
          > having a file called '.ocamlinit'. I do this in my interactive
          > Adwords API tool -- the '.ocamlinit' file just contains a list of
          > 'open...' directives. The drawback is that the '.ocamlinit' file must
          > be in the current directory (so the user must 'cd' to a particular
          > directory before invoking your custom toplevel).
          >
          > Sounds like a job for a wrapper script which invokes the preprocessor
          > (ocamlc -pp ...)
          >
        • Richard Jones
          ... Please, call me Richard :-) [open_process_out] ... Really your problem here is nothing to do with OCaml. It s a Unix issue, and one which can be solved
          Message 4 of 4 , Nov 30, 2005
          • 0 Attachment
            On Wed, Nov 30, 2005 at 12:51:18AM +0100, code17 wrote:
            > Hi, Jones, thanks for the reply!

            Please, call me Richard :-)

            [open_process_out]
            > The awkward thing of this solution is that now you'll have two processes
            > running concurrently for this simplest task, one for stdin/stdout
            > interface, the other behind is the real evaluator. All of these is just
            > because I want to add a few lines to the toplevel at the beginning.

            Really your problem here is nothing to do with OCaml. It's a Unix
            issue, and one which can be solved using the program "expect" (see:
            http://en.wikipedia.org/wiki/Expect, http://expect.nist.gov/). In
            particular, study the expect command "interact".

            I see there is even a version of expect for Windows.

            Rich.

            --
            Richard Jones, CTO Merjis Ltd.
            Merjis - web marketing and technology - http://merjis.com
            Team Notepad - intranets and extranets for business - http://team-notepad.com
          Your message has been successfully submitted and would be delivered to recipients shortly.