(index<- )        ./libstd/run.rs

   1  // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  //! Process spawning.
  12  
  13  #[allow(missing_doc)];
  14  
  15  use cell::Cell;
  16  use comm::{stream, SharedChan};
  17  use libc::{pid_t, c_int};
  18  use libc;
  19  use prelude::*;
  20  use rt::io::native::process;
  21  use rt::io;
  22  use task;
  23  
  24  /**
  25   * A value representing a child process.
  26   *
  27   * The lifetime of this value is linked to the lifetime of the actual
  28   * process - the Process destructor calls self.finish() which waits
  29   * for the process to terminate.
  30   */
  31  pub struct Process {
  32      priv inner: process::Process,
  33  }
  34  
  35  /// Options that can be given when starting a Process.
  36  pub struct ProcessOptions<'self> {
  37  
  38      /**
  39       * If this is None then the new process will have the same initial
  40       * environment as the parent process.
  41       *
  42       * If this is Some(vec-of-names-and-values) then the new process will
  43       * have an environment containing the given named values only.
  44       */
  45      env: Option<~[(~str, ~str)]>,
  46  
  47      /**
  48       * If this is None then the new process will use the same initial working
  49       * directory as the parent process.
  50       *
  51       * If this is Some(path) then the new process will use the given path
  52       * for its initial working directory.
  53       */
  54      dir: Option<&'self Path>,
  55  
  56      /**
  57       * If this is None then a new pipe will be created for the new process's
  58       * input and Process.input() will provide a Writer to write to this pipe.
  59       *
  60       * If this is Some(file-descriptor) then the new process will read its input
  61       * from the given file descriptor, Process.input_redirected() will return
  62       * true, and Process.input() will fail.
  63       */
  64      in_fd: Option<c_int>,
  65  
  66      /**
  67       * If this is None then a new pipe will be created for the new program's
  68       * output and Process.output() will provide a Reader to read from this pipe.
  69       *
  70       * If this is Some(file-descriptor) then the new process will write its output
  71       * to the given file descriptor, Process.output_redirected() will return
  72       * true, and Process.output() will fail.
  73       */
  74      out_fd: Option<c_int>,
  75  
  76      /**
  77       * If this is None then a new pipe will be created for the new program's
  78       * error stream and Process.error() will provide a Reader to read from this pipe.
  79       *
  80       * If this is Some(file-descriptor) then the new process will write its error output
  81       * to the given file descriptor, Process.error_redirected() will return true, and
  82       * and Process.error() will fail.
  83       */
  84      err_fd: Option<c_int>,
  85  }
  86  
  87  impl <'self> ProcessOptions<'self> {
  88      /// Return a ProcessOptions that has None in every field.
  89      pub fn new<'a>() -> ProcessOptions<'a> {
  90          ProcessOptions {
  91              env: None,
  92              dir: None,
  93              in_fd: None,
  94              out_fd: None,
  95              err_fd: None,
  96          }
  97      }
  98  }
  99  
 100  /// The output of a finished process.
 101  pub struct ProcessOutput {
 102  
 103      /// The status (exit code) of the process.
 104      status: int,
 105  
 106      /// The data that the process wrote to stdout.
 107      output: ~[u8],
 108  
 109      /// The data that the process wrote to stderr.
 110      error: ~[u8],
 111  }
 112  
 113  impl Process {
 114      /**
 115       * Spawns a new Process.
 116       *
 117       * # Arguments
 118       *
 119       * * prog - The path to an executable.
 120       * * args - Vector of arguments to pass to the child process.
 121       * * options - Options to configure the environment of the process,
 122       *             the working directory and the standard IO streams.
 123       */
 124      pub fn new(prog&str, args&[~str], optionsProcessOptions) -> Process {
 125          let ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options;
 126          let inner = process::Process::new(prog, args, env, dir,
 127                                            in_fd, out_fd, err_fd);
 128          Process { inner: inner }
 129      }
 130  
 131      /// Returns the unique id of the process
 132      pub fn get_id(&self) -> pid_t { self.inner.id() }
 133  
 134      /**
 135       * Returns an io::Writer that can be used to write to this Process's stdin.
 136       *
 137       * Fails if there is no stdin available (it's already been removed by
 138       * take_input)
 139       */
 140      pub fn input<'a>(&'a mut self) -> &'a mut io::Writer { self.inner.input() }
 141  
 142      /**
 143       * Returns an io::Reader that can be used to read from this Process's stdout.
 144       *
 145       * Fails if there is no stdout available (it's already been removed by
 146       * take_output)
 147       */
 148      pub fn output<'a>(&'a mut self) -> &'a mut io::Reader { self.inner.output() }
 149  
 150      /**
 151       * Returns an io::Reader that can be used to read from this Process's stderr.
 152       *
 153       * Fails if there is no stderr available (it's already been removed by
 154       * take_error)
 155       */
 156      pub fn error<'a>(&'a mut self) -> &'a mut io::Reader { self.inner.error() }
 157  
 158      /**
 159       * Closes the handle to the child process's stdin.
 160       */
 161      pub fn close_input(&mut self) {
 162          self.inner.take_input();
 163      }
 164  
 165      fn close_outputs(&mut self) {
 166          self.inner.take_output();
 167          self.inner.take_error();
 168      }
 169  
 170      /**
 171       * Closes the handle to stdin, waits for the child process to terminate,
 172       * and returns the exit code.
 173       *
 174       * If the child has already been finished then the exit code is returned.
 175       */
 176      pub fn finish(&mut self) -> int { self.inner.wait() }
 177  
 178      /**
 179       * Closes the handle to stdin, waits for the child process to terminate, and
 180       * reads and returns all remaining output of stdout and stderr, along with
 181       * the exit code.
 182       *
 183       * If the child has already been finished then the exit code and any
 184       * remaining unread output of stdout and stderr will be returned.
 185       *
 186       * This method will fail if the child process's stdout or stderr streams
 187       * were redirected to existing file descriptors.
 188       */
 189      pub fn finish_with_output(&mut self) -> ProcessOutput {
 190          self.inner.take_input(); // close stdin
 191          let output = Cell::new(self.inner.take_output());
 192          let error = Cell::new(self.inner.take_error());
 193  
 194          fn read_everything(r&mut io::Reader) -> ~[u8] {
 195              let mut ret = ~[];
 196              let mut buf = [0, ..1024];
 197              loop {
 198                  match r.read(buf) {
 199                      Some(n) => { ret.push_all(buf.slice_to(n)); }
 200                      None => break
 201                  }
 202              }
 203              return ret;
 204          }
 205  
 206          // Spawn two entire schedulers to read both stdout and sterr
 207          // in parallel so we don't deadlock while blocking on one
 208          // or the other. FIXME (#2625): Surely there's a much more
 209          // clever way to do this.
 210          let (p, ch) = stream();
 211          let ch = SharedChan::new(ch);
 212          let ch_clone = ch.clone();
 213          do task::spawn_sched(task::SingleThreaded) {
 214              match error.take() {
 215                  Some(ref mut e) => ch.send((2, read_everything(*e))),
 216                  None => ch.send((2, ~[]))
 217              }
 218          }
 219          do task::spawn_sched(task::SingleThreaded) {
 220              match output.take() {
 221                  Some(ref mut e) => ch_clone.send((1, read_everything(*e))),
 222                  None => ch_clone.send((1, ~[]))
 223              }
 224          }
 225  
 226          let status = self.finish();
 227  
 228          let (errs, outs) = match (p.recv(), p.recv()) {
 229              ((1, o), (2, e)) => (e, o),
 230              ((2, e), (1, o)) => (e, o),
 231              ((x, _), (y, _)) => {
 232                  fail2!("unexpected file numbers: {}, {}", x, y);
 233              }
 234          };
 235  
 236          return ProcessOutput {status: status,
 237                                output: outs,
 238                                error: errs};
 239      }
 240  
 241      /**
 242       * Terminates the process, giving it a chance to clean itself up if
 243       * this is supported by the operating system.
 244       *
 245       * On Posix OSs SIGTERM will be sent to the process. On Win32
 246       * TerminateProcess(..) will be called.
 247       */
 248      pub fn destroy(&mut self) {
 249          self.inner.signal(io::process::PleaseExitSignal);
 250          self.finish();
 251      }
 252  
 253      /**
 254       * Terminates the process as soon as possible without giving it a
 255       * chance to clean itself up.
 256       *
 257       * On Posix OSs SIGKILL will be sent to the process. On Win32
 258       * TerminateProcess(..) will be called.
 259       */
 260      pub fn force_destroy(&mut self) {
 261          self.inner.signal(io::process::MustDieSignal);
 262          self.finish();
 263      }
 264  }
 265  
 266  /**
 267   * Spawns a process and waits for it to terminate. The process will
 268   * inherit the current stdin/stdout/stderr file descriptors.
 269   *
 270   * # Arguments
 271   *
 272   * * prog - The path to an executable
 273   * * args - Vector of arguments to pass to the child process
 274   *
 275   * # Return value
 276   *
 277   * The process's exit code
 278   */
 279  #[fixed_stack_segment] #[inline(never)]
 280  pub fn process_status(prog&str, args&[~str]) -> int {
 281      let mut prog = Process::new(prog, args, ProcessOptions {
 282          env: None,
 283          dir: None,
 284          in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }),
 285          out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }),
 286          err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) })
 287      });
 288      prog.finish()
 289  }
 290  
 291  /**
 292   * Spawns a process, records all its output, and waits for it to terminate.
 293   *
 294   * # Arguments
 295   *
 296   * * prog - The path to an executable
 297   * * args - Vector of arguments to pass to the child process
 298   *
 299   * # Return value
 300   *
 301   * The process's stdout/stderr output and exit code.
 302   */
 303  pub fn process_output(prog&str, args&[~str]) -> ProcessOutput {
 304      let mut prog = Process::new(prog, args, ProcessOptions::new());
 305      prog.finish_with_output()
 306  }
 307  
 308  #[cfg(test)]
 309  mod tests {
 310      use libc::c_int;
 311      use option::{Option, None, Some};
 312      use os;
 313      use path::Path;
 314      use run;
 315      use str;
 316      use unstable::running_on_valgrind;
 317      use rt::io::native::file;
 318      use rt::io::{Writer, Reader};
 319  
 320      #[test]
 321      #[cfg(not(target_os="android"))]
 322      fn test_process_status() {
 323          assert_eq!(run::process_status("false", []), 1);
 324          assert_eq!(run::process_status("true", []), 0);
 325      }
 326      #[test]
 327      #[cfg(target_os="android")]
 328      fn test_process_status() {
 329          assert_eq!(run::process_status("/system/bin/sh", [~"-c",~"false"]), 1);
 330          assert_eq!(run::process_status("/system/bin/sh", [~"-c",~"true"]), 0);
 331      }
 332  
 333      #[test]
 334      #[cfg(not(target_os="android"))]
 335      fn test_process_output_output() {
 336  
 337          let run::ProcessOutput {status, output, error}
 338               = run::process_output("echo", [~"hello"]);
 339          let output_str = str::from_utf8(output);
 340  
 341          assert_eq!(status, 0);
 342          assert_eq!(output_str.trim().to_owned(), ~"hello");
 343          // FIXME #7224
 344          if !running_on_valgrind() {
 345              assert_eq!(error, ~[]);
 346          }
 347      }
 348      #[test]
 349      #[cfg(target_os="android")]
 350      fn test_process_output_output() {
 351  
 352          let run::ProcessOutput {status, output, error}
 353               = run::process_output("/system/bin/sh", [~"-c",~"echo hello"]);
 354          let output_str = str::from_utf8(output);
 355  
 356          assert_eq!(status, 0);
 357          assert_eq!(output_str.trim().to_owned(), ~"hello");
 358          // FIXME #7224
 359          if !running_on_valgrind() {
 360              assert_eq!(error, ~[]);
 361          }
 362      }
 363  
 364      #[test]
 365      #[cfg(not(target_os="android"))]
 366      fn test_process_output_error() {
 367  
 368          let run::ProcessOutput {status, output, error}
 369               = run::process_output("mkdir", [~"."]);
 370  
 371          assert_eq!(status, 1);
 372          assert_eq!(output, ~[]);
 373          assert!(!error.is_empty());
 374      }
 375      #[test]
 376      #[cfg(target_os="android")]
 377      fn test_process_output_error() {
 378  
 379          let run::ProcessOutput {status, output, error}
 380               = run::process_output("/system/bin/mkdir", [~"."]);
 381  
 382          assert_eq!(status, 255);
 383          assert_eq!(output, ~[]);
 384          assert!(!error.is_empty());
 385      }
 386  
 387      #[test]
 388      fn test_pipes() {
 389  
 390          let pipe_in = os::pipe();
 391          let pipe_out = os::pipe();
 392          let pipe_err = os::pipe();
 393  
 394          let mut proc = run::Process::new("cat", [], run::ProcessOptions {
 395              dir: None,
 396              env: None,
 397              in_fd: Some(pipe_in.input),
 398              out_fd: Some(pipe_out.out),
 399              err_fd: Some(pipe_err.out)
 400          });
 401  
 402          os::close(pipe_in.input);
 403          os::close(pipe_out.out);
 404          os::close(pipe_err.out);
 405  
 406          let expected = ~"test";
 407          writeclose(pipe_in.out, expected);
 408          let actual = readclose(pipe_out.input);
 409          readclose(pipe_err.input);
 410          proc.finish();
 411  
 412          assert_eq!(expected, actual);
 413      }
 414  
 415      fn writeclose(fd: c_int, s: &str) {
 416          let mut writer = file::FileDesc::new(fd);
 417          writer.write(s.as_bytes());
 418      }
 419  
 420      fn readclose(fd: c_int) -> ~str {
 421          let mut res = ~[];
 422          let mut reader = file::FileDesc::new(fd);
 423          let mut buf = [0, ..1024];
 424          loop {
 425              match reader.read(buf) {
 426                  Some(n) => { res.push_all(buf.slice_to(n)); }
 427                  None => break
 428              }
 429          }
 430          str::from_utf8_owned(res)
 431      }
 432  
 433      #[test]
 434      #[cfg(not(target_os="android"))]
 435      fn test_finish_once() {
 436          let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
 437          assert_eq!(prog.finish(), 1);
 438      }
 439      #[test]
 440      #[cfg(target_os="android")]
 441      fn test_finish_once() {
 442          let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"false"],
 443                                           run::ProcessOptions::new());
 444          assert_eq!(prog.finish(), 1);
 445      }
 446  
 447      #[test]
 448      #[cfg(not(target_os="android"))]
 449      fn test_finish_twice() {
 450          let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
 451          assert_eq!(prog.finish(), 1);
 452          assert_eq!(prog.finish(), 1);
 453      }
 454      #[test]
 455      #[cfg(target_os="android")]
 456      fn test_finish_twice() {
 457          let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"false"],
 458                                           run::ProcessOptions::new());
 459          assert_eq!(prog.finish(), 1);
 460          assert_eq!(prog.finish(), 1);
 461      }
 462  
 463      #[test]
 464      #[cfg(not(target_os="android"))]
 465      fn test_finish_with_output_once() {
 466  
 467          let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
 468          let run::ProcessOutput {status, output, error}
 469              = prog.finish_with_output();
 470          let output_str = str::from_utf8(output);
 471  
 472          assert_eq!(status, 0);
 473          assert_eq!(output_str.trim().to_owned(), ~"hello");
 474          // FIXME #7224
 475          if !running_on_valgrind() {
 476              assert_eq!(error, ~[]);
 477          }
 478      }
 479      #[test]
 480      #[cfg(target_os="android")]
 481      fn test_finish_with_output_once() {
 482  
 483          let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
 484                                           run::ProcessOptions::new());
 485          let run::ProcessOutput {status, output, error}
 486              = prog.finish_with_output();
 487          let output_str = str::from_utf8(output);
 488  
 489          assert_eq!(status, 0);
 490          assert_eq!(output_str.trim().to_owned(), ~"hello");
 491          // FIXME #7224
 492          if !running_on_valgrind() {
 493              assert_eq!(error, ~[]);
 494          }
 495      }
 496  
 497      #[test]
 498      #[cfg(not(target_os="android"))]
 499      fn test_finish_with_output_twice() {
 500  
 501          let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
 502          let run::ProcessOutput {status, output, error}
 503              = prog.finish_with_output();
 504  
 505          let output_str = str::from_utf8(output);
 506  
 507          assert_eq!(status, 0);
 508          assert_eq!(output_str.trim().to_owned(), ~"hello");
 509          // FIXME #7224
 510          if !running_on_valgrind() {
 511              assert_eq!(error, ~[]);
 512          }
 513  
 514          let run::ProcessOutput {status, output, error}
 515              = prog.finish_with_output();
 516  
 517          assert_eq!(status, 0);
 518          assert_eq!(output, ~[]);
 519          // FIXME #7224
 520          if !running_on_valgrind() {
 521              assert_eq!(error, ~[]);
 522          }
 523      }
 524      #[test]
 525      #[cfg(target_os="android")]
 526      fn test_finish_with_output_twice() {
 527  
 528          let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
 529                                           run::ProcessOptions::new());
 530          let run::ProcessOutput {status, output, error}
 531              = prog.finish_with_output();
 532  
 533          let output_str = str::from_utf8(output);
 534  
 535          assert_eq!(status, 0);
 536          assert_eq!(output_str.trim().to_owned(), ~"hello");
 537          // FIXME #7224
 538          if !running_on_valgrind() {
 539              assert_eq!(error, ~[]);
 540          }
 541  
 542          let run::ProcessOutput {status, output, error}
 543              = prog.finish_with_output();
 544  
 545          assert_eq!(status, 0);
 546          assert_eq!(output, ~[]);
 547          // FIXME #7224
 548          if !running_on_valgrind() {
 549              assert_eq!(error, ~[]);
 550          }
 551      }
 552  
 553      #[cfg(unix,not(target_os="android"))]
 554      fn run_pwd(dir: Option<&Path>) -> run::Process {
 555          run::Process::new("pwd", [], run::ProcessOptions {
 556              dir: dir,
 557              .. run::ProcessOptions::new()
 558          })
 559      }
 560      #[cfg(unix,target_os="android")]
 561      fn run_pwd(dir: Option<&Path>) -> run::Process {
 562          run::Process::new("/system/bin/sh", [~"-c",~"pwd"], run::ProcessOptions {
 563              dir: dir,
 564              .. run::ProcessOptions::new()
 565          })
 566      }
 567  
 568      #[cfg(windows)]
 569      fn run_pwd(dir: Option<&Path>) -> run::Process {
 570          run::Process::new("cmd", [~"/c", ~"cd"], run::ProcessOptions {
 571              dir: dir,
 572              .. run::ProcessOptions::new()
 573          })
 574      }
 575  
 576      #[test]
 577      fn test_keep_current_working_dir() {
 578          let mut prog = run_pwd(None);
 579  
 580          let output = str::from_utf8(prog.finish_with_output().output);
 581          let parent_dir = os::getcwd();
 582          let child_dir = Path::new(output.trim());
 583  
 584          let parent_stat = parent_dir.stat().unwrap();
 585          let child_stat = child_dir.stat().unwrap();
 586  
 587          assert_eq!(parent_stat.st_dev, child_stat.st_dev);
 588          assert_eq!(parent_stat.st_ino, child_stat.st_ino);
 589      }
 590  
 591      #[test]
 592      fn test_change_working_directory() {
 593          // test changing to the parent of os::getcwd() because we know
 594          // the path exists (and os::getcwd() is not expected to be root)
 595          let parent_dir = os::getcwd().dir_path();
 596          let mut prog = run_pwd(Some(&parent_dir));
 597  
 598          let output = str::from_utf8(prog.finish_with_output().output);
 599          let child_dir = Path::new(output.trim());
 600  
 601          let parent_stat = parent_dir.stat().unwrap();
 602          let child_stat = child_dir.stat().unwrap();
 603  
 604          assert_eq!(parent_stat.st_dev, child_stat.st_dev);
 605          assert_eq!(parent_stat.st_ino, child_stat.st_ino);
 606      }
 607  
 608      #[cfg(unix,not(target_os="android"))]
 609      fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
 610          run::Process::new("env", [], run::ProcessOptions {
 611              env: env,
 612              .. run::ProcessOptions::new()
 613          })
 614      }
 615      #[cfg(unix,target_os="android")]
 616      fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
 617          run::Process::new("/system/bin/sh", [~"-c",~"set"], run::ProcessOptions {
 618              env: env,
 619              .. run::ProcessOptions::new()
 620          })
 621      }
 622  
 623      #[cfg(windows)]
 624      fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
 625          run::Process::new("cmd", [~"/c", ~"set"], run::ProcessOptions {
 626              env: env,
 627              .. run::ProcessOptions::new()
 628          })
 629      }
 630  
 631      #[test]
 632      #[cfg(not(target_os="android"))]
 633      fn test_inherit_env() {
 634          if running_on_valgrind() { return; }
 635  
 636          let mut prog = run_env(None);
 637          let output = str::from_utf8(prog.finish_with_output().output);
 638  
 639          let r = os::env();
 640          for &(ref k, ref v) in r.iter() {
 641              // don't check windows magical empty-named variables
 642              assert!(k.is_empty() || output.contains(format!("{}={}", *k, *v)));
 643          }
 644      }
 645      #[test]
 646      #[cfg(target_os="android")]
 647      fn test_inherit_env() {
 648          if running_on_valgrind() { return; }
 649  
 650          let mut prog = run_env(None);
 651          let output = str::from_utf8(prog.finish_with_output().output);
 652  
 653          let r = os::env();
 654          for &(ref k, ref v) in r.iter() {
 655              // don't check android RANDOM variables
 656              if *k != ~"RANDOM" {
 657                  assert!(output.contains(format!("{}={}", *k, *v)) ||
 658                          output.contains(format!("{}=\'{}\'", *k, *v)));
 659              }
 660          }
 661      }
 662  
 663      #[test]
 664      fn test_add_to_env() {
 665  
 666          let mut new_env = os::env();
 667          new_env.push((~"RUN_TEST_NEW_ENV", ~"123"));
 668  
 669          let mut prog = run_env(Some(new_env));
 670          let output = str::from_utf8(prog.finish_with_output().output);
 671  
 672          assert!(output.contains("RUN_TEST_NEW_ENV=123"));
 673      }
 674  }

libstd/run.rs:100:38-100:38 -struct- definition:
/// The output of a finished process.
pub struct ProcessOutput {
references:-
303: pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput {
189:     pub fn finish_with_output(&mut self) -> ProcessOutput {
236:         return ProcessOutput {status: status,


libstd/run.rs:35:55-35:55 -struct- definition:
/// Options that can be given when starting a Process.
pub struct ProcessOptions<'self> {
references:-
281:     let mut prog = Process::new(prog, args, ProcessOptions {
125:         let ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options;
87: impl <'self> ProcessOptions<'self> {
124:     pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Process {
89:     pub fn new<'a>() -> ProcessOptions<'a> {
90:         ProcessOptions {


libstd/run.rs:194:8-194:8 -fn- definition:
        fn read_everything(r: &mut io::Reader) -> ~[u8] {
            let mut ret = ~[];
references:-
215:                 Some(ref mut e) => ch.send((2, read_everything(*e))),
221:                 Some(ref mut e) => ch_clone.send((1, read_everything(*e))),


libstd/run.rs:30:4-30:4 -struct- definition:
 */
pub struct Process {
references:-
124:     pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Process {
128:         Process { inner: inner }
113: impl Process {