(index<- )        ./libstd/rt/uv/process.rs

   1  // Copyright 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  use prelude::*;
  12  use cell::Cell;
  13  use libc;
  14  use ptr;
  15  use util;
  16  use vec;
  17  
  18  use rt::io::process::*;
  19  use rt::uv;
  20  use rt::uv::uvio::UvPipeStream;
  21  use rt::uv::uvll;
  22  
  23  /// A process wraps the handle of the underlying uv_process_t.
  24  pub struct Process(*uvll::uv_process_t);
  25  
  26  impl uv::Watcher for Process {}
  27  
  28  impl Process {
  29      /// Creates a new process, ready to spawn inside an event loop
  30      pub fn new() -> Process {
  31          let handle = unsafe { uvll::malloc_handle(uvll::UV_PROCESS) };
  32          assert!(handle.is_not_null());
  33          let mut retProcess = uv::NativeHandle::from_native_handle(handle);
  34          ret.install_watcher_data();
  35          return ret;
  36      }
  37  
  38      /// Spawn a new process inside the specified event loop.
  39      ///
  40      /// The `config` variable will be passed down to libuv, and the `exit_cb`
  41      /// will be run only once, when the process exits.
  42      ///
  43      /// Returns either the corresponding process object or an error which
  44      /// occurred.
  45      pub fn spawn(&mut self, loop_&uv::Loop, mut configProcessConfig,
  46                   exit_cbuv::ExitCallback)
  47                      -> Result<~[Option<UvPipeStream>], uv::UvError>
  48      {
  49          let cwd = config.cwd.map(|s| s.to_c_str());
  50  
  51          extern fn on_exit(p*uvll::uv_process_t,
  52                            exit_statuslibc::c_int,
  53                            term_signallibc::c_int) {
  54              let mut pProcess = uv::NativeHandle::from_native_handle(p);
  55              let err = match exit_status {
  56                  0 => None,
  57                  _ => uv::status_to_maybe_uv_error(-1)
  58              };
  59              p.get_watcher_data().exit_cb.take_unwrap()(p,
  60                                                         exit_status as int,
  61                                                         term_signal as int,
  62                                                         err);
  63          }
  64  
  65          let io = util::replace(&mut config.io, ~[]);
  66          let mut stdio = vec::with_capacity::<uvll::uv_stdio_container_t>(io.len());
  67          let mut ret_io = vec::with_capacity(io.len());
  68          unsafe {
  69              vec::raw::set_len(&mut stdio, io.len());
  70              for (slot, other) in stdio.iter().zip(io.move_iter()) {
  71                  let io = set_stdio(slot as *uvll::uv_stdio_container_t, other);
  72                  ret_io.push(io);
  73              }
  74          }
  75  
  76          let exit_cb = Cell::new(exit_cb);
  77          let ret_io = Cell::new(ret_io);
  78          do with_argv(config.program, config.args) |argv| {
  79              do with_env(config.env) |envp| {
  80                  let options = uvll::uv_process_options_t {
  81                      exit_cb: on_exit,
  82                      file: unsafe { *argv },
  83                      args: argv,
  84                      env: envp,
  85                      cwd: match cwd {
  86                          Some(ref cwd) => cwd.with_ref(|p| p),
  87                          None => ptr::null(),
  88                      },
  89                      flags: 0,
  90                      stdio_count: stdio.len() as libc::c_int,
  91                      stdio: stdio.as_imm_buf(|p, _| p),
  92                      uid: 0,
  93                      gid: 0,
  94                  };
  95  
  96                  match unsafe {
  97                      uvll::spawn(loop_.native_handle(), **self, options)
  98                  } {
  99                      0 => {
 100                          (*self).get_watcher_data().exit_cb = Some(exit_cb.take());
 101                          Ok(ret_io.take())
 102                      }
 103                      err => Err(uv::UvError(err))
 104                  }
 105              }
 106          }
 107      }
 108  
 109      /// Sends a signal to this process.
 110      ///
 111      /// This is a wrapper around `uv_process_kill`
 112      pub fn kill(&self, signumint) -> Result<(), uv::UvError> {
 113          match unsafe {
 114              uvll::process_kill(self.native_handle(), signum as libc::c_int)
 115          } {
 116              0 => Ok(()),
 117              err => Err(uv::UvError(err))
 118          }
 119      }
 120  
 121      /// Returns the process id of a spawned process
 122      pub fn pid(&self) -> libc::pid_t {
 123          unsafe { uvll::process_pid(**self) as libc::pid_t }
 124      }
 125  
 126      /// Closes this handle, invoking the specified callback once closed
 127      pub fn close(self, cbuv::NullCallback) {
 128          {
 129              let mut this = self;
 130              let data = this.get_watcher_data();
 131              assert!(data.close_cb.is_none());
 132              data.close_cb = Some(cb);
 133          }
 134  
 135          unsafe { uvll::close(self.native_handle(), close_cb); }
 136  
 137          extern fn close_cb(handle*uvll::uv_process_t) {
 138              let mut processProcess = uv::NativeHandle::from_native_handle(handle);
 139              process.get_watcher_data().close_cb.take_unwrap()();
 140              process.drop_watcher_data();
 141              unsafe { uvll::free_handle(handle as *libc::c_void) }
 142          }
 143      }
 144  }
 145  
 146  unsafe fn set_stdio(dst*uvll::uv_stdio_container_t,
 147                      ioStdioContainer) -> Option<UvPipeStream> {
 148      match io {
 149          Ignored => {
 150              uvll::set_stdio_container_flags(dst, uvll::STDIO_IGNORE);
 151              None
 152          }
 153          InheritFd(fd) => {
 154              uvll::set_stdio_container_flags(dst, uvll::STDIO_INHERIT_FD);
 155              uvll::set_stdio_container_fd(dst, fd);
 156              None
 157          }
 158          CreatePipe(pipe, readable, writable) => {
 159              let mut flags = uvll::STDIO_CREATE_PIPE as libc::c_int;
 160              if readable {
 161                  flags |= uvll::STDIO_READABLE_PIPE as libc::c_int;
 162              }
 163              if writable {
 164                  flags |= uvll::STDIO_WRITABLE_PIPE as libc::c_int;
 165              }
 166              let handle = pipe.pipe.as_stream().native_handle();
 167              uvll::set_stdio_container_flags(dst, flags);
 168              uvll::set_stdio_container_stream(dst, handle);
 169              Some(pipe.bind())
 170          }
 171      }
 172  }
 173  
 174  /// Converts the program and arguments to the argv array expected by libuv
 175  fn with_argv<T>(prog&str, args&[~str], f&fn(**libc::c_char) -> T) -> T {
 176      // First, allocation space to put all the C-strings (we need to have
 177      // ownership of them somewhere
 178      let mut c_strs = vec::with_capacity(args.len() + 1);
 179      c_strs.push(prog.to_c_str());
 180      for arg in args.iter() {
 181          c_strs.push(arg.to_c_str());
 182      }
 183  
 184      // Next, create the char** array
 185      let mut c_args = vec::with_capacity(c_strs.len() + 1);
 186      for s in c_strs.iter() {
 187          c_args.push(s.with_ref(|p| p));
 188      }
 189      c_args.push(ptr::null());
 190      c_args.as_imm_buf(|buf, _| f(buf))
 191  }
 192  
 193  /// Converts the environment to the env array expected by libuv
 194  fn with_env<T>(envOption<&[(~str, ~str)]>, f&fn(**libc::c_char) -> T) -> T {
 195      let env = match env {
 196          Some(s) => s,
 197          None => { return f(ptr::null()); }
 198      };
 199      // As with argv, create some temporary storage and then the actual array
 200      let mut envp = vec::with_capacity(env.len());
 201      for &(ref key, ref value) in env.iter() {
 202          envp.push(format!("{}={}", *key, *value).to_c_str());
 203      }
 204      let mut c_envp = vec::with_capacity(envp.len() + 1);
 205      for s in envp.iter() {
 206          c_envp.push(s.with_ref(|p| p));
 207      }
 208      c_envp.push(ptr::null());
 209      c_envp.as_imm_buf(|buf, _| f(buf))
 210  }
 211  
 212  impl uv::NativeHandle<*uvll::uv_process_t> for Process {
 213      fn from_native_handle(handle*uvll::uv_process_t) -> Process {
 214          Process(handle)
 215      }
 216      fn native_handle(&self) -> *uvll::uv_process_t {
 217          match self { &Process(ptr) => ptr }
 218      }
 219  }

libstd/rt/uv/process.rs:23:63-23:63 -struct- definition:
/// A process wraps the handle of the underlying uv_process_t.
pub struct Process(*uvll::uv_process_t);
references:-
212: impl uv::NativeHandle<*uvll::uv_process_t> for Process {
54:             let mut p: Process = uv::NativeHandle::from_native_handle(p);
26: impl uv::Watcher for Process {}
138:             let mut process: Process = uv::NativeHandle::from_native_handle(handle);
213:     fn from_native_handle(handle: *uvll::uv_process_t) -> Process {
30:     pub fn new() -> Process {
28: impl Process {
33:         let mut ret: Process = uv::NativeHandle::from_native_handle(handle);
libstd/rt/uv/mod.rs:
135: pub type ExitCallback = ~fn(Process, int, int, Option<UvError>);
libstd/rt/uv/uvio.rs:
1533:     process: process::Process,


libstd/rt/uv/process.rs:137:8-137:8 -fn- definition:
        extern fn close_cb(handle: *uvll::uv_process_t) {
            let mut process: Process = uv::NativeHandle::from_native_handle(handle);
references:-
135:         unsafe { uvll::close(self.native_handle(), close_cb); }


libstd/rt/uv/process.rs:174:75-174:75 -fn- definition:
/// Converts the program and arguments to the argv array expected by libuv
fn with_argv<T>(prog: &str, args: &[~str], f: &fn(**libc::c_char) -> T) -> T {
references:-
78:         do with_argv(config.program, config.args) |argv| {


libstd/rt/uv/process.rs:193:64-193:64 -fn- definition:
/// Converts the environment to the env array expected by libuv
fn with_env<T>(env: Option<&[(~str, ~str)]>, f: &fn(**libc::c_char) -> T) -> T {
references:-
79:             do with_env(config.env) |envp| {


libstd/rt/uv/process.rs:145:1-145:1 -fn- definition:

unsafe fn set_stdio(dst: *uvll::uv_stdio_container_t,
references:-
71:                 let io = set_stdio(slot as *uvll::uv_stdio_container_t, other);


libstd/rt/uv/process.rs:51:8-51:8 -fn- definition:
        extern fn on_exit(p: *uvll::uv_process_t,
                          exit_status: libc::c_int,
references:-
81:                     exit_cb: on_exit,