On 02/02/2012 11:00, [email protected] wrote:
> Hi, I need run 3 external program and redirected output: first | second | 
> third
> 
> For example: 
>    df -hT | grep -v -E 'tmpfs|ecryptfs' | grep 'sda2'
> it gives
>    /dev/sda2     ext4     19G   11G  7,6G  58% /
> 
> I use this 
> http://wiki.lazarus.freepascal.org/Executing_External_Programs#How_to_redirect_output_with_TProcess
>  sample code. It works fine for  first | second.
> 
> For three programs I try edit it:
> 
> 
> function threePipe(inputA, inputB, inputC: string): string;
> var
>  FirstProcess, SecondProcess, ThirdProcess: TProcess;
>  Buffer: array[0..127] of char;
>  ReadCount: Integer;
>  ReadSize: Integer;
> begin
>  FirstProcess  := TProcess.Create(nil);
>  SecondProcess := TProcess.Create(nil);
>  ThirdProcess := TProcess.Create(nil);
> 
>  FirstProcess.Options  := [poUsePipes];
>  SecondProcess.Options := [poUsePipes];
>  ThirdProcess.Options  := [poUsePipes,poStderrToOutPut];
> 
>  FirstProcess.CommandLine  := inputA;
>  SecondProcess.CommandLine := inputB;
>  ThirdProcess.CommandLine := inputC;
> 
>  FirstProcess.Execute;
>  SecondProcess.Execute;
>  ThirdProcess.Execute;
> 

while (Firstprocess.Running or SecondProcess.Running or ThirdProcess.Running) do
begin
  if Firstprocess.Running then
    begin
      if (FirstProcess.Output.NumbytesAvailable > 0) then 
        begin                                                           
          ReadSize := FirstProcess.Output.NumBytesAvailable;
          if ReadSize > SizeOf(Buffer) then 
            ReadSize := SizeOf(Buffer); 
          ReadCount := FirstProcess.Output.Read(Buffer[0], ReadSize);
          SecondProcess.Input.Write(Buffer[0], ReadCount);
          // at the end of this, we have written max. 128 bytes to 
SecondProcess' input
        end;  // if no more bytes, we could terminate the FirstProcess but 
having it here
              // may race when the lot starts: when FirstProcess just started 
but has no output yet
              // or if for some reason it stops on the way; 
              // some checking for first process's errors may be a good idea 
too, here.
    end
  else
    SecondProcess.CloseInput;  // when first process ends, input to second also 
ends

  if SecondProcess.Running then
    begin
      if (SecondProcess.Output.NumBytesAvailable > 0) then
        begin
          ReadSize := SecondProcess.Output.NumBytesAvailable;
          if ReadSize > SizeOf(Buffer) then  
            ReadSize := SizeOf(Buffer);  
          ReadCount := SecondProcess.Output.Read(Buffer[0], ReadSize);
          ThirdProcess.Input.Write(Buffer[0], ReadCount);
        end;
    end
  else
    ThirdProcess.CloseInput;
        
  if ThirdProcess.Running then
    begin
      if (ThirdProcess.Output.NumbytesAvailable >0) then
        begin
          ReadSize := ThirdProcess.Output.NumBytesAvailable;
          if ReadSize > SizeOf(Buffer) then  
            ReadSize := SizeOf(Buffer);  
          if ReadSize > 0 then
            begin
              ReadCount := ThirdProcess.Output.Read(Buffer, ReadSize);
              Write(Copy(Buffer,0, ReadCount));  // i think no writeln, but 
write (grep gives you ^M on each line IIRC)
            end;
        end;
    end;

end;

>  while FirstProcess.Running or (FirstProcess.Output.NumBytesAvailable > 0) do
>  begin
>    if FirstProcess.Output.NumBytesAvailable > 0 then
>    begin
>      ReadSize := FirstProcess.Output.NumBytesAvailable;
>      if ReadSize > SizeOf(Buffer) then
>        ReadSize := SizeOf(Buffer);
>      ReadCount := FirstProcess.Output.Read(Buffer[0], ReadSize);
>      SecondProcess.Input.Write(Buffer[0], ReadCount);
>    end;
>  end;
>  SecondProcess.CloseInput;
> 
>  while SecondProcess.Running or (SecondProcess.Output.NumBytesAvailable > 0) 
> do
>  begin
>    if SecondProcess.Output.NumBytesAvailable > 0 then
>    begin
>      ReadSize := SecondProcess.Output.NumBytesAvailable;
>      if ReadSize > SizeOf(Buffer) then
>        ReadSize := SizeOf(Buffer);
>      ReadCount := SecondProcess.Output.Read(Buffer[0], ReadSize);
>      ThirdProcess.Input.Write(Buffer[0], ReadCount);
>    end;
>  end;
>  ThirdProcess.CloseInput;
> 
> 
>  while ThirdProcess.Running do
>    Sleep(1);
>  ReadSize := ThirdProcess.Output.NumBytesAvailable;
>  if ReadSize > SizeOf(Buffer) then
>    ReadSize := SizeOf(Buffer);
>  if ReadSize > 0 then
>  begin
>    ReadCount := ThirdProcess.Output.Read(Buffer, ReadSize);
>    //WriteLn(Copy(Buffer,0, ReadCount));
>  end
>  else
>    WriteLn('grep did not find what we searched for. ', 
> ThirdProcess.ExitStatus);
> 

//  here;
>  FirstProcess.Free;
>  SecondProcess.Free;
>  ThirdProcess.Free;
>  threePipe := Copy(Buffer,0, ReadCount); // and this will be nonsense - 
> better have another variable accounting all bytes out from third process
> end;
> 
> 
> 
> But after i call 
>    Label1.Caption:=threePipe('df -hT', 'grep -v -E ''tmpfs|ecryptfs''', 'grep 
> ''sda2''');
> function my application end with infinite loop.
> 
> Where I do an error?
> 

Thought compiled only.

But:
- uses same buffer to pass between stages, adjusts buffer to size between 
reads, does not
stop to read the whole buffer output from first process or second process, just 
passes buffer
as it comes


--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to