let rec wait_for_children retcode =
  try
    match wait () with
      pid,WEXITED n -> wait_for_children (retcode lor n)
    | pid,_ -> wait_for_children 127
  with
     Unix_error(ECHILD,_,_) -> retcode;;

let pipeline cmd args input =
  let from_pipe,to_pipe = pipe () in
  match fork() with
    0 ->
      close from_pipe;
      dup2 input stdin;
      close input;
      dup2 to_pipe stdout;
      close to_pipe;
      mon_exec cmd args
  | pid ->
      close input;
      close to_pipe;
      from_pipe;;

let end_pipeline cmd args input =
  match fork() with
    0 ->
      dup2 input stdin;
      close input;
      mon_exec cmd args
  | pid ->
      close input;;

let rec create_pipeline cmd_list input =
  match cmd_list with
    [] -> ()
  | (cmd,args)::[] -> end_pipeline cmd args input
  | (cmd,args)::tail -> create_pipeline tail (pipeline cmd args input);;

let pipeline_commands cmd_list =
  create_pipeline cmd_list (dup stdin);
  exit(wait_for_children 0);;