Skip to content

Additional documentation additions #452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 2, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions src/unistd.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Standard symbolic constants and types
//!
//! Safe wrappers around functions found in libc "unistd.h" header

use {Errno, Error, Result, NixPath};
use fcntl::{fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::F_SETFD;
Expand Down Expand Up @@ -344,6 +344,12 @@ fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
args_p
}

/// Replace the current process image with a new one (see
/// [exec(3)](http://man7.org/linux/man-pages/man3/exec.3.html)).
///
/// See the `::nix::unistd::execve` system call for additional details. `execv`
/// performs the same action but does not allow for customization of the
/// environment for the new process.
#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
let args_p = to_exec_array(argv);
Expand All @@ -355,6 +361,24 @@ pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
Err(Error::Sys(Errno::last()))
}


/// Replace the current process image with a new one (see
/// [execve(2)](http://man7.org/linux/man-pages/man2/execve.2.html)).
///
/// The execve system call allows for another process to be "called" which will
/// replace the current process image. That is, this process becomes the new
/// command that is run. On success, this function will not return. Instead,
/// the new program will run until it exits.
///
/// If an error occurs, this function will return with an indication of the
/// cause of failure. See
/// [execve(2)#errors](http://man7.org/linux/man-pages/man2/execve.2.html#ERRORS)
/// for a list of potential problems that maight cause execv to fail.
///
/// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice
/// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element
/// in the `args` list is an argument to the new process. Each element in the
/// `env` list should be a string in the form "key=value".
#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
let args_p = to_exec_array(args);
Expand All @@ -367,6 +391,15 @@ pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void>
Err(Error::Sys(Errno::last()))
}

/// Replace the current process image with a new one and replicate shell `PATH`
/// searching behavior (see
/// [exec(3)](http://man7.org/linux/man-pages/man3/exec.3.html)).
///
/// See `::nix::unistd::execve` for additoinal details. `execvp` behaves the
/// same as execv except that it will examine the `PATH` environment variables
/// for file names not specified with a leading slash. For example, `execv`
/// would not work if "bash" was specified for the path argument, but `execvp`
/// would assuming that a bash executable was on the system `PATH`.
#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
let args_p = to_exec_array(args);
Expand All @@ -378,6 +411,37 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
Err(Error::Sys(Errno::last()))
}

/// Daemonize this process by detaching from the controlling terminal (see
/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
///
/// When a process is launched it is typically associated with a parent and it,
/// in turn, by its controlling terminal/process. In order for a process to run
/// in the "background" it must daemonize itself by detaching itself. Under
/// posix, this is done by doing the following:
///
/// 1. Parent process (this one) forks
/// 2. Parent process exits
/// 3. Child process continues to run.
///
/// `nochdir`:
///
/// * `nochdir = true`: The current working directory after daemonizing will
/// be the current working directory.
/// * `nochdir = false`: The current working directory after daemonizing will
/// be the root direcory, `/`.
///
/// `noclose`:
///
/// * `noclose = true`: The process' current stdin, stdout, and stderr file
/// descriptors will remain identical after daemonizing.
/// * `noclose = false`: The process' stdin, stdout, and stderr will point to
/// `/dev/null` after daemonizing.
///
/// The underlying implementation (in libc) calls both
/// [fork(2)](http://man7.org/linux/man-pages/man2/fork.2.html) and
/// [setsid(2)](http://man7.org/linux/man-pages/man2/setsid.2.html) and, as
/// such, error that could be returned by either of those functions could also
/// show up as errors here.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What good is an abstraction, if we need to look at the implementation for documentation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am referring users to the libc man pages, not to an implementation. I think the former is acceptable. This is basically the same approach taking by the man pages for this call. We can go further with time, but I think this is a reasonable start.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
Errno::result(res).map(drop)
Expand Down