(* Программа join - соединяет две программы каналом *)
uses linux,stdio;

function fatal (s:pchar):integer;
begin
  perror (s);
  halt (1);
end;


function join (com1, com2:ppchar):integer;
var
  fdin,fdout:longint;
  status:integer;
begin
  (* Создать дочерний процесс для выполнения команд *)
  case fork of
    -1:			(* ошибка *)
      fatal ('Ошибка 1 вызова fork в программе join');
    0:			(* дочерний процесс *)
      ;
    else			(* родительский процесс *)
    begin
      wait(@status);
      join:=status;
      exit;
    end;
  end;
  (* Остаток процедуры, выполняемой дочерним процессом *)
  (* Создать канал *)
  if not assignpipe(fdin,fdout) then
    fatal ('Ошибка вызова pipe в программе join');
  (* Создать еще один процесс *)
  case fork of
    -1:
      (* ошибка *)
      fatal ('Ошибка 2 вызова fork в программе join');
    0:
    begin
      (* процесс, выполняющий запись *)
      dup2 (fdout, 1);		(* направить ст. вывод в канал *)
      fdclose (fdin);		(* сохранить дескрипторы файлов *)
      fdclose (fdout);
      execvp (com1[0], com1, envp);
      (* Если execvp возвращает значение, то произошла ошибка *)
      fatal ('Ошибка 1 вызова execvp в программе join');
    end;
    else
    begin
      (* процесс, выполняющий чтение *)
      dup2 (fdin, 0);		(* направить ст. ввод из канала *)
      fdclose (fdin);
      fdclose (fdout);
      execvp (com2[0], com2, envp);
      fatal ('Ошибка 2 вызова execvp в программе join');
    end;
  end;
end;


const
  one:array [0..3] of pchar = ('ls', '-l', '/usr/lib', nil);
  two:array [0..2] of pchar = ('grep', '^d', nil);
var 
  ret:integer;
begin
  ret := join (one, two);
  writeln ('Возврат из программы join ', ret);
  halt (0);
end.
