comp.lang.ada
 help / color / mirror / Atom feed
* Running external program, getting output
@ 2003-06-22 11:51 Jarle Thorsen
  2003-06-22 13:07 ` Ludovic Brenta
  2003-06-22 17:20 ` Martin Krischik
  0 siblings, 2 replies; 10+ messages in thread
From: Jarle Thorsen @ 2003-06-22 11:51 UTC (permalink / raw)


As far as I have gathered the best way of (non OS-specific) running an
external program from Ada is using the Spawn procedure in g-os_lib, correct
?

But how do I get the output from the command that I run? Lets say that I
want to run "ls" for example.....

-- 
Jarle Thorsen




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 11:51 Running external program, getting output Jarle Thorsen
@ 2003-06-22 13:07 ` Ludovic Brenta
  2003-06-22 13:43   ` sk
  2003-06-22 17:20 ` Martin Krischik
  1 sibling, 1 reply; 10+ messages in thread
From: Ludovic Brenta @ 2003-06-22 13:07 UTC (permalink / raw)


Jarle Thorsen <jarle@genbukan.no> writes:

> As far as I have gathered the best way of (non OS-specific) running
> an external program from Ada is using the Spawn procedure in
> g-os_lib, correct ?
> 
> But how do I get the output from the command that I run? Lets say
> that I want to run "ls" for example.....

Spawn does not allow you to read from the child process' standard
output.  For this, I'd use popen(2) but unfortunately, GNAT doesn't
provide a binding to it.  Here is a quick and dirty example:

with Interfaces.C; use Interfaces.C;
with Interfaces.C_Streams;
with System;
with Ada.Text_IO;

procedure Spawn_And_Read is

   type Popen_Mode is (Read, Write, Read_Write);
   Popen_Error : exception;

   procedure Popen (Command : in String;
                    Mode : in Popen_Mode;
                    Stream : out Interfaces.C_Streams.FILEs)
   --  Executes COMMAND in a subshell, and attaches STREAM to the
   --  subprocess' standard input and/or output.  If MODE = Read,
   --  you can read the process' output from STREAM.  If MODE = Write,
   --  you can write into the process' standard input with STREAM.
   --  if MODE = Read_Write, both operations are allowed.
   is
      function Popen_Native (Command, Mode : Interfaces.C.char_array)
                            return Interfaces.C_Streams.FILEs;
      pragma Import (C, Popen_Native, "popen");
      use type Interfaces.C_Streams.FILEs;
   begin
      case Mode is
         when Read =>
            Stream := Popen_Native (To_C (Command), To_C ("r"));
         when Write =>
            Stream := Popen_Native (To_C (Command), To_C ("w"));
         when Read_Write =>
            Stream := Popen_Native (To_C (Command), To_C ("rw"));
      end case;
      if Stream = Interfaces.C_Streams.NULL_Stream then
         raise Popen_Error;
      end if;
   end Popen;

   procedure Pclose (Stream : Interfaces.C_Streams.FILEs);
   pragma Import (C, Pclose, "pclose");

   Stream : Interfaces.C_Streams.FILEs;
   Buffer : String (1 .. 100);
   Bytes_Read : Interfaces.C_Streams.size_t;
begin
   Popen (Command => "ls -lF /", Mode => Read, Stream => Stream);
   while Interfaces.C_Streams.Feof (Stream) = 0 loop
      Bytes_Read := Interfaces.C_Streams.fread (Buffer => Buffer'Address,
                                                Size => 1,
                                                Count => Buffer'Length,
                                                Stream => Stream);
      Ada.Text_IO.Put (Buffer (1 .. Integer (Bytes_Read)));
   end loop;

   Pclose (Stream);
end Spawn_And_Read;




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 13:07 ` Ludovic Brenta
@ 2003-06-22 13:43   ` sk
  2003-06-22 15:39     ` Jarle Thorsen
  0 siblings, 1 reply; 10+ messages in thread
From: sk @ 2003-06-22 13:43 UTC (permalink / raw)
  To: comp.lang.ada

... or look at Adapower where J. Rogers has provided a
"popen" binding ...


-- 
-------------------------------------------------
-- Merge vertically for real address
--
--     s n p @ t . o
--      k i e k c c m
-------------------------------------------------




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 13:43   ` sk
@ 2003-06-22 15:39     ` Jarle Thorsen
  2003-06-22 19:21       ` David C. Hoos
  2003-06-22 19:25       ` sk
  0 siblings, 2 replies; 10+ messages in thread
From: Jarle Thorsen @ 2003-06-22 15:39 UTC (permalink / raw)


sk <sknipe@ktc.com> writes:

> ... or look at Adapower where J. Rogers has provided a
> "popen" binding ...

Do you have a direct link to this ?

-- 
Jarle Thorsen
     Q:   But why do brunettes take the pill ?
     A:   Wishful Thinking.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 11:51 Running external program, getting output Jarle Thorsen
  2003-06-22 13:07 ` Ludovic Brenta
@ 2003-06-22 17:20 ` Martin Krischik
  2003-06-25 20:39   ` Jarle Thorsen
  1 sibling, 1 reply; 10+ messages in thread
From: Martin Krischik @ 2003-06-22 17:20 UTC (permalink / raw)


Jarle Thorsen wrote:

> As far as I have gathered the best way of (non OS-specific) running an
> external program from Ada is using the Spawn procedure in g-os_lib,
> correct ?
> 
> But how do I get the output from the command that I run? Lets say that I
> want to run "ls" for example.....

AdaCL has a support class do just this. See TestCommand (test 3) on how to
do it:

http://adacl.sourceforge.net/html/TestCommand-Main__adb.htm

You find AdaCL at:

http://www.ada.krischik.com

Also, you can use the GNAT.Expect package.

With Regads

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 15:39     ` Jarle Thorsen
@ 2003-06-22 19:21       ` David C. Hoos
  2003-06-22 19:25       ` sk
  1 sibling, 0 replies; 10+ messages in thread
From: David C. Hoos @ 2003-06-22 19:21 UTC (permalink / raw)



"Jarle Thorsen" <jarle@genbukan.no> wrote in message
news:m28yrujf3q.fsf@maskin.flamestrike.no-ip.org...
> sk <sknipe@ktc.com> writes:
>
> > ... or look at Adapower where J. Rogers has provided a
> > "popen" binding ...
>
> Do you have a direct link to this ?
www.adapower.com/reuse/pipes.html

>
> --
> Jarle Thorsen
>      Q:   But why do brunettes take the pill ?
>      A:   Wishful Thinking.
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>
>





^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 15:39     ` Jarle Thorsen
  2003-06-22 19:21       ` David C. Hoos
@ 2003-06-22 19:25       ` sk
  1 sibling, 0 replies; 10+ messages in thread
From: sk @ 2003-06-22 19:25 UTC (permalink / raw)
  To: comp.lang.ada

www.adapower.com

-> "The Ada Source Code Treasury"

-> "Ada Source Code Packages for Reuse"

-> "Ada Binding to Pipes "


-- 
-------------------------------------------------
-- Merge vertically for real address
--
--     s n p @ t . o
--      k i e k c c m
-------------------------------------------------




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-22 17:20 ` Martin Krischik
@ 2003-06-25 20:39   ` Jarle Thorsen
  2003-06-26  2:04     ` sk
  2003-06-27 17:47     ` Warren W. Gay VE3WWG
  0 siblings, 2 replies; 10+ messages in thread
From: Jarle Thorsen @ 2003-06-25 20:39 UTC (permalink / raw)


Martin Krischik <krischik@users.sourceforge.net> writes:
> Jarle Thorsen wrote:
> 
> > As far as I have gathered the best way of (non OS-specific) running an
> > external program from Ada is using the Spawn procedure in g-os_lib,
> > correct ?
> > 
> > But how do I get the output from the command that I run? Lets say that I
> > want to run "ls" for example.....
> 
> AdaCL has a support class do just this. See TestCommand (test 3) on how to
> do it:
> 
> http://adacl.sourceforge.net/html/TestCommand-Main__adb.htm
> 
> You find AdaCL at:
> 
> http://www.ada.krischik.com
> 
> Also, you can use the GNAT.Expect package.

Reading your suggestions and also packages provided by other posters I am
getting really unsure which way to go...

My main focus is making it as portable as possible, yet as simple as
possible.

My program will 90% percent of the time wait for the spawned program to end
before printing its output, but will on some occations read information
from the program's pipe while it is still running....

Any clues on which solution to choose ?

-- 
Jarle Thorsen




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-25 20:39   ` Jarle Thorsen
@ 2003-06-26  2:04     ` sk
  2003-06-27 17:47     ` Warren W. Gay VE3WWG
  1 sibling, 0 replies; 10+ messages in thread
From: sk @ 2003-06-26  2:04 UTC (permalink / raw)
  To: comp.lang.ada

Whether you choose "popen" binding or AdaCL (I have not
looked at AdaCL yet), you probably do not want to use the
"Gnat.Os_Lib" spawn functions as well.

If you look at the source for Gnat.Os_Lib.Spawn, and follow
the code trail to the "C" source file "a-adainit.c", function
"__gnat_portable_spawn", you will see the typical

fork ()
if child then

     -- do child stuff

else -- if parent

     -- do parent stuff

end if;

So, if you use Gnat.Os_Lib.Spawn and also implement "popen",
or similar, you will probably end up with a double spawn;
a situation *I* would prefer to avoid.

If you choose to implement yourself, rather than use either
J.Rogers "popen" binding or the AdaCL package(s), you might
use "__gnat_portable_spawn" as a starting point for your own
efforts.

-- 
-------------------------------------------------
-- Merge vertically for real address
--
--     s n p @ t . o
--      k i e k c c m
-------------------------------------------------




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Running external program, getting output
  2003-06-25 20:39   ` Jarle Thorsen
  2003-06-26  2:04     ` sk
@ 2003-06-27 17:47     ` Warren W. Gay VE3WWG
  1 sibling, 0 replies; 10+ messages in thread
From: Warren W. Gay VE3WWG @ 2003-06-27 17:47 UTC (permalink / raw)


Jarle Thorsen wrote:
> Martin Krischik <krischik@users.sourceforge.net> writes:
>>Jarle Thorsen wrote:
>>>As far as I have gathered the best way of (non OS-specific) running an
>>>external program from Ada is using the Spawn procedure in g-os_lib,
>>>correct ?
>>>
>>>But how do I get the output from the command that I run? Lets say that I
>>>want to run "ls" for example.....
>>
>>AdaCL has a support class do just this. See TestCommand (test 3) on how to
>>do it:
>>
>>http://adacl.sourceforge.net/html/TestCommand-Main__adb.htm
>>
>>You find AdaCL at:
>>
>>http://www.ada.krischik.com
>>
>>Also, you can use the GNAT.Expect package.
> 
> Reading your suggestions and also packages provided by other posters I am
> getting really unsure which way to go...
> 
> My main focus is making it as portable as possible, yet as simple as
> possible.
> 
> My program will 90% percent of the time wait for the spawned program to end
> before printing its output, but will on some occations read information
> from the program's pipe while it is still running....

What you are experiencing is the fact that commands that provide output
(to the pipe), have buffered I/O in many situations (perhaps not all).
This buffer is in the application that is being run.

Iff the output is buffered, then indeed, you will not see a small amount
of output, until the running application closes the standard output (this
forces a flush of the write buffer).

BUT(!) most (if not all) UNIX program libraries are designed to NOT
buffer output when the output device is a tty or a pipe.

However, if you end up using the popen(3) call in libc that returns a
FILE *, then this too will use a buffer. This is probably what is
causing your "experience".

To change this, you need to do a setbuf(File,_IONBF) in C terms
to eliminate the buffer. I havn't actually tried this with peopen(3),
but I can't see why it would fail. This is certainly
what you want in this case. To do this, you'll either have to find
the appropriate Binding API to cause this, or you may have to
create your own binding to accomplish this.

 >
 > Any clues on which solution to choose ?

So to answer your question, if the buffering is a concern, then
choose the one that permits you to control buffering. If neither
does it, then other factors enter into the choice. ;-)

-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2003-06-27 17:47 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-22 11:51 Running external program, getting output Jarle Thorsen
2003-06-22 13:07 ` Ludovic Brenta
2003-06-22 13:43   ` sk
2003-06-22 15:39     ` Jarle Thorsen
2003-06-22 19:21       ` David C. Hoos
2003-06-22 19:25       ` sk
2003-06-22 17:20 ` Martin Krischik
2003-06-25 20:39   ` Jarle Thorsen
2003-06-26  2:04     ` sk
2003-06-27 17:47     ` Warren W. Gay VE3WWG

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox