mirror of
https://github.com/uutils/coreutils
synced 2024-10-15 12:24:09 +00:00
implement kill
This commit is contained in:
parent
610da56b68
commit
8f4d9ea42e
1
Makefile
1
Makefile
|
@ -30,6 +30,7 @@ PROGS := \
|
||||||
head \
|
head \
|
||||||
|
|
||||||
UNIX_PROGS := \
|
UNIX_PROGS := \
|
||||||
|
kill \
|
||||||
logname \
|
logname \
|
||||||
users \
|
users \
|
||||||
whoami \
|
whoami \
|
||||||
|
|
|
@ -97,7 +97,6 @@ To do
|
||||||
- hostid
|
- hostid
|
||||||
- install
|
- install
|
||||||
- join
|
- join
|
||||||
- kill
|
|
||||||
- lbracket
|
- lbracket
|
||||||
- libstdbuf
|
- libstdbuf
|
||||||
- link
|
- link
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! show_error(
|
macro_rules! show_error(
|
||||||
($exitcode:expr, $($args:expr),+) => ({
|
($exitcode:expr, $($args:expr),+) => ({
|
||||||
::std::os::set_exit_status($exitcode);
|
::std::os::set_exit_status($exitcode as int);
|
||||||
safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
||||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||||
})
|
})
|
||||||
|
@ -30,6 +30,14 @@ macro_rules! show_warning(
|
||||||
macro_rules! crash(
|
macro_rules! crash(
|
||||||
($exitcode:expr, $($args:expr),+) => ({
|
($exitcode:expr, $($args:expr),+) => ({
|
||||||
show_error!($exitcode, $($args),+);
|
show_error!($exitcode, $($args),+);
|
||||||
|
unsafe { ::std::libc::exit($exitcode as ::std::libc::c_int); }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! exit(
|
||||||
|
($exitcode:expr) => ({
|
||||||
unsafe { ::std::libc::exit($exitcode); }
|
unsafe { ::std::libc::exit($exitcode); }
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
209
kill/kill.rs
Normal file
209
kill/kill.rs
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
#![crate_id(name="kill", vers="0.0.1", author="Maciej Dziardziel")]
|
||||||
|
#![feature(macro_rules)]
|
||||||
|
#![feature(phase)]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the uutils coreutils package.
|
||||||
|
*
|
||||||
|
* (c) Maciej Dziardziel <fiedzia@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE file
|
||||||
|
* that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern crate getopts;
|
||||||
|
extern crate collections;
|
||||||
|
extern crate serialize;
|
||||||
|
|
||||||
|
#[phase(syntax, link)] extern crate log;
|
||||||
|
|
||||||
|
use std::os;
|
||||||
|
use std::from_str::from_str;
|
||||||
|
use std::io::process::Process;
|
||||||
|
|
||||||
|
use getopts::{
|
||||||
|
getopts,
|
||||||
|
optopt,
|
||||||
|
optflag,
|
||||||
|
optflagopt,
|
||||||
|
usage,
|
||||||
|
};
|
||||||
|
|
||||||
|
use signals::{
|
||||||
|
ALL_SIGNALS,
|
||||||
|
DEFAULT_SIGNAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod signals;
|
||||||
|
|
||||||
|
#[path = "../common/util.rs"]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
static NAME: &'static str = "kill";
|
||||||
|
static VERSION: &'static str = "0.0.1";
|
||||||
|
|
||||||
|
static EXIT_OK: i32 = 0;
|
||||||
|
static EXIT_ERR: i32 = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub enum Mode {
|
||||||
|
Kill,
|
||||||
|
Table,
|
||||||
|
List,
|
||||||
|
Help,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = os::args();
|
||||||
|
|
||||||
|
let opts = ~[
|
||||||
|
optflag("h", "help", "display this help and exit"),
|
||||||
|
optflag("V", "version", "output version information and exit"),
|
||||||
|
optopt("s", "signal", "specify the <signal> to be sent", "SIGNAL"),
|
||||||
|
optflagopt("l", "list", "list all signal names, or convert one to a name", "LIST"),
|
||||||
|
optflag("L", "table", "list all signal names in a nice table"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let usage = usage("[options] <pid> [...]", opts);
|
||||||
|
|
||||||
|
|
||||||
|
let matches = match getopts(args.tail(), opts) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => {
|
||||||
|
let msg = format!("{}\n{}", e.to_err_msg(), get_help_text(NAME, usage));
|
||||||
|
show_error!(EXIT_ERR, "{}", msg);
|
||||||
|
return
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let mode = if matches.opt_present("version") {
|
||||||
|
Version
|
||||||
|
} else if matches.opt_present("help") {
|
||||||
|
Help
|
||||||
|
} else if matches.opt_present("table") {
|
||||||
|
Table
|
||||||
|
} else if matches.opt_present("list") {
|
||||||
|
List
|
||||||
|
} else {
|
||||||
|
Kill
|
||||||
|
};
|
||||||
|
|
||||||
|
match mode {
|
||||||
|
Kill => kill(matches.opt_str("signal").unwrap_or(~"9"), matches.free),
|
||||||
|
Table => table(),
|
||||||
|
List => list(matches.opt_str("list")),
|
||||||
|
Help => help(NAME, usage),
|
||||||
|
Version => version(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version() {
|
||||||
|
println!("{} {}", NAME, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn table() {
|
||||||
|
|
||||||
|
let mut name_width = 0;
|
||||||
|
/* Compute the maximum width of a signal name. */
|
||||||
|
for s in ALL_SIGNALS.iter() {
|
||||||
|
if s.name.len() > name_width {
|
||||||
|
name_width = s.name.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
|
||||||
|
print!("{0: >#2} {1: <#8}", idx+1, signal.name);
|
||||||
|
//TODO: obtain max signal width here
|
||||||
|
|
||||||
|
if (idx+1) % 7 == 0 {
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_signal(signal_name_or_value: ~str) {
|
||||||
|
for signal in ALL_SIGNALS.iter() {
|
||||||
|
if signal.name == signal_name_or_value || ("SIG" + signal.name) == signal_name_or_value {
|
||||||
|
println!("{}", signal.value)
|
||||||
|
exit!(EXIT_OK)
|
||||||
|
} else if signal_name_or_value == signal.value.to_str() {
|
||||||
|
println!("{}", signal.name);
|
||||||
|
exit!(EXIT_OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crash!(EXIT_ERR, "unknown signal name {}", signal_name_or_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_signals() {
|
||||||
|
let mut pos = 0;
|
||||||
|
for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
|
||||||
|
pos += signal.name.len();
|
||||||
|
print!("{}", signal.name);
|
||||||
|
if idx > 0 && pos > 73 {
|
||||||
|
println!("");
|
||||||
|
pos = 0;
|
||||||
|
} else {
|
||||||
|
pos += 1;
|
||||||
|
print!(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list(arg: Option<~str>) {
|
||||||
|
match arg {
|
||||||
|
Some(x) => print_signal(x),
|
||||||
|
None => print_signals(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_help_text(progname: &str, usage: &str) -> ~str {
|
||||||
|
let msg = format!("Usage: \n {0} {1}", progname, usage);
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
|
||||||
|
fn help(progname: &str, usage: &str) {
|
||||||
|
println!("{}", get_help_text(progname, usage));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signal_by_name_or_value(signal_name_or_value:~str) -> Option<uint> {
|
||||||
|
if signal_name_or_value == ~"0"{
|
||||||
|
return Some(0);
|
||||||
|
}
|
||||||
|
for signal in ALL_SIGNALS.iter() {
|
||||||
|
let long_name = "SIG" + signal.name;
|
||||||
|
if signal.name == signal_name_or_value || (signal_name_or_value == signal.value.to_str()) || (long_name == signal_name_or_value) {
|
||||||
|
return Some(signal.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kill(signalname: ~str, pids: std::vec::Vec<~str>) {
|
||||||
|
let optional_signal_value = signal_by_name_or_value(signalname.clone());
|
||||||
|
let mut signal_value:uint = DEFAULT_SIGNAL;
|
||||||
|
match optional_signal_value {
|
||||||
|
Some(x) => signal_value = x,
|
||||||
|
None => {
|
||||||
|
crash!(EXIT_ERR, "unknown signal name {}", signalname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for pid in pids.iter() {
|
||||||
|
match from_str::<i32>(*pid) {
|
||||||
|
Some(x) => {
|
||||||
|
let result = Process::kill(x, signal_value as int);
|
||||||
|
match result {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(_) => ()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
crash!(EXIT_ERR, "failed to parse argument {}", signalname)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
138
kill/signals.rs
Normal file
138
kill/signals.rs
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the uutils coreutils package.
|
||||||
|
*
|
||||||
|
* (c) Maciej Dziardziel <fiedzia@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE file
|
||||||
|
* that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub static DEFAULT_SIGNAL:uint = 15;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Signal<'a> { pub name:&'a str, pub value: uint}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Linux Programmer's Manual
|
||||||
|
|
||||||
|
1 HUP 2 INT 3 QUIT 4 ILL 5 TRAP 6 ABRT 7 BUS
|
||||||
|
8 FPE 9 KILL 10 USR1 11 SEGV 12 USR2 13 PIPE 14 ALRM
|
||||||
|
15 TERM 16 STKFLT 17 CHLD 18 CONT 19 STOP 20 TSTP 21 TTIN
|
||||||
|
22 TTOU 23 URG 24 XCPU 25 XFSZ 26 VTALRM 27 PROF 28 WINCH
|
||||||
|
29 POLL 30 PWR 31 SYS
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub static ALL_SIGNALS:[Signal<'static>, ..31] = [
|
||||||
|
Signal{ name: "HUP", value:1 },
|
||||||
|
Signal{ name: "INT", value:2 },
|
||||||
|
Signal{ name: "QUIT", value:3 },
|
||||||
|
Signal{ name: "ILL", value:4 },
|
||||||
|
Signal{ name: "TRAP", value:5 },
|
||||||
|
Signal{ name: "ABRT", value:6 },
|
||||||
|
Signal{ name: "BUS", value:7 },
|
||||||
|
Signal{ name: "FPE", value:8 },
|
||||||
|
Signal{ name: "KILL", value:9 },
|
||||||
|
Signal{ name: "USR1", value:10 },
|
||||||
|
Signal{ name: "SEGV", value:11 },
|
||||||
|
Signal{ name: "USR2", value:12 },
|
||||||
|
Signal{ name: "PIPE", value:13 },
|
||||||
|
Signal{ name: "ALRM", value:14 },
|
||||||
|
Signal{ name: "TERM", value:15 },
|
||||||
|
Signal{ name: "STKFLT", value:16 },
|
||||||
|
Signal{ name: "CHLD", value:17 },
|
||||||
|
Signal{ name: "CONT", value:18 },
|
||||||
|
Signal{ name: "STOP", value:19 },
|
||||||
|
Signal{ name: "TSTP", value:20 },
|
||||||
|
Signal{ name: "TTIN", value:21 },
|
||||||
|
Signal{ name: "TTOU", value:22 },
|
||||||
|
Signal{ name: "URG", value:23 },
|
||||||
|
Signal{ name: "XCPU", value:24 },
|
||||||
|
Signal{ name: "XFSZ", value:25 },
|
||||||
|
Signal{ name: "VTALRM", value:26 },
|
||||||
|
Signal{ name: "PROF", value:27 },
|
||||||
|
Signal{ name: "WINCH", value:28 },
|
||||||
|
Signal{ name: "POLL", value:29 },
|
||||||
|
Signal{ name: "PWR", value:30 },
|
||||||
|
Signal{ name: "SYS", value:31 },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html
|
||||||
|
|
||||||
|
|
||||||
|
No Name Default Action Description
|
||||||
|
1 SIGHUP terminate process terminal line hangup
|
||||||
|
2 SIGINT terminate process interrupt program
|
||||||
|
3 SIGQUIT create core image quit program
|
||||||
|
4 SIGILL create core image illegal instruction
|
||||||
|
5 SIGTRAP create core image trace trap
|
||||||
|
6 SIGABRT create core image abort program (formerly SIGIOT)
|
||||||
|
7 SIGEMT create core image emulate instruction executed
|
||||||
|
8 SIGFPE create core image floating-point exception
|
||||||
|
9 SIGKILL terminate process kill program
|
||||||
|
10 SIGBUS create core image bus error
|
||||||
|
11 SIGSEGV create core image segmentation violation
|
||||||
|
12 SIGSYS create core image non-existent system call invoked
|
||||||
|
13 SIGPIPE terminate process write on a pipe with no reader
|
||||||
|
14 SIGALRM terminate process real-time timer expired
|
||||||
|
15 SIGTERM terminate process software termination signal
|
||||||
|
16 SIGURG discard signal urgent condition present on socket
|
||||||
|
17 SIGSTOP stop process stop (cannot be caught or ignored)
|
||||||
|
18 SIGTSTP stop process stop signal generated from keyboard
|
||||||
|
19 SIGCONT discard signal continue after stop
|
||||||
|
20 SIGCHLD discard signal child status has changed
|
||||||
|
21 SIGTTIN stop process background read attempted from control terminal
|
||||||
|
22 SIGTTOU stop process background write attempted to control terminal
|
||||||
|
23 SIGIO discard signal I/O is possible on a descriptor (see fcntl(2))
|
||||||
|
24 SIGXCPU terminate process cpu time limit exceeded (see setrlimit(2))
|
||||||
|
25 SIGXFSZ terminate process file size limit exceeded (see setrlimit(2))
|
||||||
|
26 SIGVTALRM terminate process virtual time alarm (see setitimer(2))
|
||||||
|
27 SIGPROF terminate process profiling timer alarm (see setitimer(2))
|
||||||
|
28 SIGWINCH discard signal Window size change
|
||||||
|
29 SIGINFO discard signal status request from keyboard
|
||||||
|
30 SIGUSR1 terminate process User defined signal 1
|
||||||
|
31 SIGUSR2 terminate process User defined signal 2
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub static ALL_SIGNALS:[Signal<'static>, ..31] = [
|
||||||
|
Signal{ name: "HUP", value:1 },
|
||||||
|
Signal{ name: "INT", value:2 },
|
||||||
|
Signal{ name: "QUIT", value:3 },
|
||||||
|
Signal{ name: "ILL", value:4 },
|
||||||
|
Signal{ name: "TRAP", value:5 },
|
||||||
|
Signal{ name: "ABRT", value:6 },
|
||||||
|
Signal{ name: "EMT", value:7 },
|
||||||
|
Signal{ name: "FPE", value:8 },
|
||||||
|
Signal{ name: "KILL", value:9 },
|
||||||
|
Signal{ name: "BUS", value:10 },
|
||||||
|
Signal{ name: "SEGV", value:11 },
|
||||||
|
Signal{ name: "SYS", value:12 },
|
||||||
|
Signal{ name: "PIPE", value:13 },
|
||||||
|
Signal{ name: "ALRM", value:14 },
|
||||||
|
Signal{ name: "TERM", value:15 },
|
||||||
|
Signal{ name: "URG", value:16 },
|
||||||
|
Signal{ name: "STOP", value:17 },
|
||||||
|
Signal{ name: "TSTP", value:18 },
|
||||||
|
Signal{ name: "CONT", value:19 },
|
||||||
|
Signal{ name: "CHLD", value:20 },
|
||||||
|
Signal{ name: "TTIN", value:21 },
|
||||||
|
Signal{ name: "TTOU", value:22 },
|
||||||
|
Signal{ name: "IO", value:23 },
|
||||||
|
Signal{ name: "XCPU", value:24 },
|
||||||
|
Signal{ name: "XFSZ", value:25 },
|
||||||
|
Signal{ name: "VTALRM", value:26 },
|
||||||
|
Signal{ name: "PROF", value:27 },
|
||||||
|
Signal{ name: "WINCH", value:28 },
|
||||||
|
Signal{ name: "INFO", value:29 },
|
||||||
|
Signal{ name: "USR1", value:30 },
|
||||||
|
Signal{ name: "USR2", value:31 },
|
||||||
|
];
|
Loading…
Reference in a new issue