11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -1331,6 +1331,7 @@ dependencies = [
|
|||||||
"uu_nologin",
|
"uu_nologin",
|
||||||
"uu_renice",
|
"uu_renice",
|
||||||
"uu_rev",
|
"uu_rev",
|
||||||
|
"uu_setpgid",
|
||||||
"uu_setsid",
|
"uu_setsid",
|
||||||
"uu_uuidgen",
|
"uu_uuidgen",
|
||||||
"uucore",
|
"uucore",
|
||||||
@@ -1500,6 +1501,16 @@ dependencies = [
|
|||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uu_setpgid"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"libc",
|
||||||
|
"nix",
|
||||||
|
"uucore",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uu_setsid"
|
name = "uu_setsid"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ feat_common_core = [
|
|||||||
"nologin",
|
"nologin",
|
||||||
"renice",
|
"renice",
|
||||||
"rev",
|
"rev",
|
||||||
|
"setpgid",
|
||||||
"setsid",
|
"setsid",
|
||||||
"uuidgen",
|
"uuidgen",
|
||||||
]
|
]
|
||||||
@@ -106,6 +107,7 @@ mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", pa
|
|||||||
nologin = { optional = true, version = "0.0.1", package = "uu_nologin", path = "src/uu/nologin" }
|
nologin = { optional = true, version = "0.0.1", package = "uu_nologin", path = "src/uu/nologin" }
|
||||||
renice = { optional = true, version = "0.0.1", package = "uu_renice", path = "src/uu/renice" }
|
renice = { optional = true, version = "0.0.1", package = "uu_renice", path = "src/uu/renice" }
|
||||||
rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" }
|
rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" }
|
||||||
|
setpgid = { optional = true, version = "0.0.1", package = "uu_setpgid", path = "src/uu/setpgid" }
|
||||||
setsid = { optional = true, version = "0.0.1", package = "uu_setsid", path ="src/uu/setsid" }
|
setsid = { optional = true, version = "0.0.1", package = "uu_setsid", path ="src/uu/setsid" }
|
||||||
uuidgen = { optional = true, version = "0.0.1", package = "uu_uuidgen", path ="src/uu/uuidgen" }
|
uuidgen = { optional = true, version = "0.0.1", package = "uu_uuidgen", path ="src/uu/uuidgen" }
|
||||||
|
|
||||||
|
|||||||
17
src/uu/setpgid/Cargo.toml
Normal file
17
src/uu/setpgid/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "uu_setpgid"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/setpgid.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "setpgid"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
uucore = { workspace = true }
|
||||||
|
clap = { workspace = true }
|
||||||
|
libc = { workspace = true }
|
||||||
|
nix = { workspace = true, features = ["process"] }
|
||||||
7
src/uu/setpgid/setpgid.md
Normal file
7
src/uu/setpgid/setpgid.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# setpgid
|
||||||
|
|
||||||
|
```
|
||||||
|
setpgid [options] <program> [<argument>...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run a program in a new process group
|
||||||
1
src/uu/setpgid/src/main.rs
Normal file
1
src/uu/setpgid/src/main.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uucore::bin!(uu_setpgid);
|
||||||
99
src/uu/setpgid/src/setpgid.rs
Normal file
99
src/uu/setpgid/src/setpgid.rs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// This file is part of the uutils util-linux package.
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE
|
||||||
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
use clap::{crate_version, Arg, ArgAction, Command as ClapCommand};
|
||||||
|
use uucore::{
|
||||||
|
error::{UResult, USimpleError},
|
||||||
|
format_usage, help_about, help_usage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ABOUT: &str = help_about!("setpgid.md");
|
||||||
|
const USAGE: &str = help_usage!("setpgid.md");
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
#[uucore::main]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
|
let matches = uu_app().try_get_matches_from(args)?;
|
||||||
|
|
||||||
|
let remaining_args: Vec<String> = matches
|
||||||
|
.get_many::<String>("args")
|
||||||
|
.unwrap()
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if unsafe { libc::setpgid(0, 0) } != 0 {
|
||||||
|
return Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!(
|
||||||
|
"failed to create new process group: {}",
|
||||||
|
std::io::Error::last_os_error()
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches.get_flag("foreground") {
|
||||||
|
if let Ok(tty_file) = File::open("/dev/tty") {
|
||||||
|
unsafe {
|
||||||
|
libc::tcsetpgrp(tty_file.as_raw_fd(), libc::getpgrp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// According to strace open("/dev/tty") failure is ignored.
|
||||||
|
}
|
||||||
|
|
||||||
|
let program = &remaining_args[0];
|
||||||
|
let program_args = &remaining_args[1..];
|
||||||
|
|
||||||
|
// Command line arguments can't contain NUL bytes, so unwrap() is safe here.
|
||||||
|
let program_cstr = CString::new(program.as_str()).unwrap();
|
||||||
|
let mut argv = vec![program_cstr.clone()];
|
||||||
|
for arg in program_args {
|
||||||
|
argv.push(CString::new(arg.as_str()).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let Err(e) = nix::unistd::execvp(&program_cstr, &argv);
|
||||||
|
Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!("failed to execute '{}': {}", program, e),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_family = "unix"))]
|
||||||
|
#[uucore::main]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
let _matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
|
||||||
|
|
||||||
|
Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
"`setpgid` is unavailable on non-UNIX-like platforms.",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uu_app() -> ClapCommand {
|
||||||
|
ClapCommand::new(uucore::util_name())
|
||||||
|
.version(crate_version!())
|
||||||
|
.about(ABOUT)
|
||||||
|
.override_usage(format_usage(USAGE))
|
||||||
|
.infer_long_args(true)
|
||||||
|
.arg(
|
||||||
|
Arg::new("foreground")
|
||||||
|
.short('f')
|
||||||
|
.long("foreground")
|
||||||
|
.help("Make a foreground process group")
|
||||||
|
.action(ArgAction::SetTrue),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("args")
|
||||||
|
.hide_short_help(true)
|
||||||
|
.hide_long_help(true)
|
||||||
|
.required(true)
|
||||||
|
.action(ArgAction::Append)
|
||||||
|
.num_args(1..)
|
||||||
|
.trailing_var_arg(true),
|
||||||
|
)
|
||||||
|
}
|
||||||
37
tests/by-util/test_setpgid.rs
Normal file
37
tests/by-util/test_setpgid.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// This file is part of the uutils util-linux package.
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE
|
||||||
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
use uutests::new_ucmd;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn test_nonexistent_program() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("does_not_exist")
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("failed to execute");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_pgid_changed() {
|
||||||
|
let our_pgid = unsafe { libc::getpgid(0) };
|
||||||
|
// Gets pgid of the 'cut' process from /proc
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["cut", "-d", " ", "-f", "5", "/proc/self/stat"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_does_not_match(&Regex::new(&format!("^{}$", our_pgid)).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn test_flag_after_command() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("echo")
|
||||||
|
.arg("-f")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("-f\n");
|
||||||
|
}
|
||||||
@@ -55,6 +55,10 @@ mod test_renice;
|
|||||||
#[path = "by-util/test_rev.rs"]
|
#[path = "by-util/test_rev.rs"]
|
||||||
mod test_rev;
|
mod test_rev;
|
||||||
|
|
||||||
|
#[cfg(feature = "setpgid")]
|
||||||
|
#[path = "by-util/test_setpgid.rs"]
|
||||||
|
mod test_setpgid;
|
||||||
|
|
||||||
#[cfg(feature = "setsid")]
|
#[cfg(feature = "setsid")]
|
||||||
#[path = "by-util/test_setsid.rs"]
|
#[path = "by-util/test_setsid.rs"]
|
||||||
mod test_setsid;
|
mod test_setsid;
|
||||||
|
|||||||
Reference in New Issue
Block a user