// Copyright 2016 Joe Wilm, The Alacritty Project Contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::ffi::OsStr; use std::process::{Command, Stdio}; use std::{cmp, io}; #[cfg(not(windows))] use std::os::unix::process::CommandExt; #[cfg(windows)] use std::os::windows::process::CommandExt; #[cfg(windows)] use winapi::um::winbase::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW}; /// Threading utilities pub mod thread { /// Like `thread::spawn`, but with a `name` argument pub fn spawn_named(name: S, f: F) -> ::std::thread::JoinHandle where F: FnOnce() -> T + Send + 'static, T: Send + 'static, S: Into, { ::std::thread::Builder::new().name(name.into()).spawn(f).expect("thread spawn works") } pub use std::thread::*; } pub fn limit(value: T, min: T, max: T) -> T { cmp::min(cmp::max(value, min), max) } #[cfg(not(windows))] pub fn start_daemon(program: &str, args: I) -> io::Result<()> where I: IntoIterator, S: AsRef, { unsafe { Command::new(program) .args(args) .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) .pre_exec(|| { match ::libc::fork() { -1 => return Err(io::Error::last_os_error()), 0 => (), _ => ::libc::_exit(0), } if ::libc::setsid() == -1 { return Err(io::Error::last_os_error()); } Ok(()) }) .spawn()? .wait() .map(|_| ()) } } #[cfg(windows)] pub fn start_daemon(program: &str, args: I) -> io::Result<()> where I: IntoIterator, S: AsRef, { // Setting all the I/O handles to null and setting the // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect // that console applications will run without opening a new // console window. Command::new(program) .args(args) .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) .creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW) .spawn() .map(|_| ()) } #[cfg(test)] mod tests { use super::limit; #[test] fn limit_works() { assert_eq!(10, limit(10, 0, 100)); assert_eq!(10, limit(5, 10, 100)); assert_eq!(100, limit(1000, 10, 100)); } }