Port to clap-rs
I did a number of things here: the *add, *mod, and *del utilities, as well as id recieved substantial changes, probably what you'd call a rewrite. This was of course using clap-rs. These should all be very stable at this point (except unimplemented features in usermod, grr) getty, passwd, and su are simply ported, using clap for arg parsing. I didn't change any of the logic, just swapped ArgParser for clap. Fixed a bug with passwd and unset passwords I'll open issues about the ones I didn't mention.
This commit is contained in:
Generated
+55
-1
@@ -1,3 +1,8 @@
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "arg_parser"
|
||||
version = "0.1.0"
|
||||
@@ -20,6 +25,16 @@ dependencies = [
|
||||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.5"
|
||||
@@ -65,6 +80,20 @@ name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
@@ -158,7 +187,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/redox-os/users.git#0fc602398887533c947b3f428e9fe0037f829478"
|
||||
source = "git+https://github.com/redox-os/users.git#0c56faee77dd86d0b48460b6e588e2c96a8a0d99"
|
||||
dependencies = [
|
||||
"argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"extra 0.1.0 (git+https://github.com/redox-os/libextra.git)",
|
||||
@@ -177,6 +206,11 @@ name = "scoped_threadpool"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
@@ -214,6 +248,14 @@ dependencies = [
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.4"
|
||||
@@ -229,6 +271,7 @@ name = "userutils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)",
|
||||
"clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"extra 0.1.0 (git+https://github.com/redox-os/libextra.git)",
|
||||
"liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -237,6 +280,11 @@ dependencies = [
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.4"
|
||||
@@ -257,15 +305,18 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
|
||||
"checksum arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)" = "<none>"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
|
||||
"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b8f59bcebcfe4269b09f71dab0da15b355c75916a8f975d3876ce81561893ee"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum extra 0.1.0 (git+https://github.com/redox-os/libextra.git)" = "<none>"
|
||||
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
|
||||
@@ -282,12 +333,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum redox_users 0.1.0 (git+https://github.com/redox-os/users.git)" = "<none>"
|
||||
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
|
||||
"checksum scoped_threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4ea459fe3ceff01e09534847c49860891d3ff1c12b4eb7731b67f2778fb60190"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
@@ -56,6 +56,7 @@ path = "src/bin/whoami.rs"
|
||||
|
||||
[dependencies]
|
||||
arg_parser = { git = "https://github.com/redox-os/arg-parser.git" }
|
||||
clap = "~2.29.4"
|
||||
extra = { git = "https://github.com/redox-os/libextra.git" }
|
||||
liner = "0.1"
|
||||
redox_syscall = "0.1"
|
||||
|
||||
+16
-39
@@ -1,21 +1,20 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate redox_termios;
|
||||
extern crate syscall;
|
||||
extern crate arg_parser;
|
||||
extern crate extra;
|
||||
|
||||
use std::{env, process, str};
|
||||
use std::str;
|
||||
use std::fs::File;
|
||||
use std::io::{self, ErrorKind, Read, Write, Stderr};
|
||||
use std::io::{self, ErrorKind, Read, Stderr};
|
||||
use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::process::{exit, Child, Command, Stdio};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::io::fail;
|
||||
use extra::option::OptionalExt;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{getty} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{getty} */ r#"
|
||||
NAME
|
||||
getty - set terminal mode
|
||||
|
||||
@@ -29,19 +28,16 @@ DESCRIPTION
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
-h, --help
|
||||
Display this help and exit.
|
||||
|
||||
-J
|
||||
--noclear
|
||||
-J, --noclear
|
||||
Do not clear the screen before forking login(1).
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller.
|
||||
"#; /* @MANEND */
|
||||
|
||||
const HELP_INFO: &'static str = "Try ‘getty --help’ for more information.\n";
|
||||
const DEFAULT_COLS: u32 = 80;
|
||||
const DEFAULT_LINES: u32 = 30;
|
||||
|
||||
@@ -182,37 +178,18 @@ fn daemon(tty_fd: RawFd, clear: bool, stderr: &mut Stderr) {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut stdout = io::stdout();
|
||||
let mut stderr = io::stderr();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_flag(&["J", "noclear"]);
|
||||
parser.parse(env::args());
|
||||
let args = clap_app!(getty =>
|
||||
(author: "Jeremy Soller")
|
||||
(about: "Set terminal mode")
|
||||
(@arg TTY: +required "")
|
||||
(@arg NO_CLEAR: -J --("no-clear") "Do not clear the screen before forking")
|
||||
).get_matches();
|
||||
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);;
|
||||
exit(0);
|
||||
}
|
||||
let clear = !args.is_present("NO_CLEAR");
|
||||
|
||||
if let Err(err) = parser.found_invalid() {
|
||||
stderr.write_all(err.as_bytes()).try(&mut stderr);
|
||||
stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
|
||||
stderr.flush().try(&mut stderr);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let mut clear = true;
|
||||
if parser.found("noclear") {
|
||||
clear = false
|
||||
}
|
||||
|
||||
if parser.args.len() < 1 {
|
||||
fail("getty: no TTY provided", &mut stderr);
|
||||
}
|
||||
|
||||
let tty = &parser.args[0];
|
||||
let tty = args.value_of("TTY").unwrap();
|
||||
let tty_fd = match syscall::open(tty, syscall::O_CLOEXEC | syscall::flag::O_RDWR | syscall::flag::O_NONBLOCK) {
|
||||
Ok(fd) => fd,
|
||||
Err(err) => fail(&format!("getty: failed to open TTY {}: {}", tty, err), &mut stderr),
|
||||
|
||||
+23
-46
@@ -1,24 +1,22 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate redox_users;
|
||||
|
||||
use extra::option::OptionalExt;
|
||||
|
||||
use std::{io, env};
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use redox_users::{AllGroups, UsersError};
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{groupadd} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{groupadd} */ r#"
|
||||
NAME
|
||||
groupadd - add a user group
|
||||
|
||||
SYNOPSIS
|
||||
groupadd [ -f | --force ] group
|
||||
groupadd [ -f | --force ] GROUP
|
||||
groupadd [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -44,57 +42,36 @@ AUTHOR
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
let mut stderr = io::stderr();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_flag(&["f", "force"])
|
||||
.add_opt("g", "gid");
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
let args = clap_app!(groupadd =>
|
||||
(author: "Wesley Hershberger")
|
||||
(about: "Add groups based on the system's redox_users backend")
|
||||
(@arg GROUP: +required "Add group GROUP")
|
||||
(@arg FORCE: -f --force "Force the status of the program to be 0 even if the group exists")
|
||||
(@arg GID: -g --gid "Group id. Positive integer and must not be in use")
|
||||
).get_matches();
|
||||
|
||||
let mut sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
let groupname = if parser.args.is_empty() {
|
||||
eprintln!("groupadd: no group name specified");
|
||||
exit(1);
|
||||
} else {
|
||||
&parser.args[0]
|
||||
};
|
||||
let groupname = args.value_of("GROUP").unwrap();
|
||||
|
||||
let gid = if let Some(gid) = parser.get_opt("gid") {
|
||||
let gid = gid.parse::<usize>().unwrap_or_exit(1);
|
||||
|
||||
match sys_groups.get_by_id(gid) {
|
||||
Some(_) => {
|
||||
let gid = match args.value_of("GID") {
|
||||
Some(gid) => {
|
||||
let id = gid.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_group) = sys_groups.get_by_id(id) {
|
||||
eprintln!("groupadd: group already exists");
|
||||
exit(1);
|
||||
},
|
||||
None => {
|
||||
gid
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match sys_groups.get_unique_id() {
|
||||
Some(gid) => gid,
|
||||
None => {
|
||||
eprintln!("groupadd: no available gid");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
id
|
||||
},
|
||||
None => sys_groups.get_unique_id().unwrap_or_else(|| {
|
||||
eprintln!("groupadd: no available gid");
|
||||
exit(1);
|
||||
})
|
||||
};
|
||||
|
||||
match sys_groups.add_group(groupname, gid, &[""]) {
|
||||
Ok(_) => { },
|
||||
Err(ref err) if err.downcast_ref::<UsersError>() == Some(&UsersError::AlreadyExists) && parser.found("force") => {
|
||||
Err(ref err) if err.downcast_ref::<UsersError>() == Some(&UsersError::AlreadyExists) && args.is_present("FORCE") => {
|
||||
exit(0);
|
||||
},
|
||||
Err(err) => {
|
||||
|
||||
+10
-25
@@ -1,23 +1,19 @@
|
||||
#[deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate redox_users;
|
||||
|
||||
use std::env;
|
||||
use std::io::{stdout, Write};
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use redox_users::AllGroups;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{groupdel} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{groupdel} */ r#"
|
||||
NAME
|
||||
groupdel - modify system files to delete groups
|
||||
|
||||
SYNOPSYS
|
||||
groupdel [ options ] LOGIN
|
||||
groupdel [ options ] GROUP
|
||||
groupdel [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -37,24 +33,13 @@ AUTHORS
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
let matches = clap_app!(groupdel =>
|
||||
(author: "Wesley Hershberger")
|
||||
(about: "Removes a group from the system using redox_users")
|
||||
(@arg GROUP: +required "Removes group GROUP")
|
||||
).get_matches();
|
||||
|
||||
let mut parser = ArgParser::new(9)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
|
||||
stdout.flush().unwrap();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let group = if parser.args.is_empty() {
|
||||
eprintln!("groupdel: no login specified");
|
||||
exit(1);
|
||||
} else {
|
||||
&parser.args[0]
|
||||
};
|
||||
let group = matches.value_of("GROUP").unwrap();
|
||||
|
||||
let mut sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
|
||||
+20
-37
@@ -1,18 +1,16 @@
|
||||
#[deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate redox_users;
|
||||
|
||||
use std::env;
|
||||
use std::io::{stdout, Write};
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use redox_users::AllGroups;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{groupmod} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{groupmod} */ r#"
|
||||
NAME
|
||||
groupmod - modify group information
|
||||
|
||||
@@ -45,48 +43,33 @@ AUTHORS
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
let args = clap_app!(groupmod =>
|
||||
(author: "Wesley Hershberger")
|
||||
(about: "Modify users according to the system's redox_users backend")
|
||||
(@arg GROUP: +required "Modify GROUP")
|
||||
(@arg GID: -g --gid +takes_value "Change GROUP's group id. See man page for details")
|
||||
(@arg NAME: -n --name +takes_value "Change GROUP's name")
|
||||
).get_matches();
|
||||
|
||||
let mut parser = ArgParser::new(9)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_opt("g", "gid")
|
||||
.add_opt("n", "name");
|
||||
parser.parse(env::args());
|
||||
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
|
||||
stdout.flush().unwrap();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let groupname = if parser.args.is_empty() {
|
||||
eprintln!("groupmod: no login specified");
|
||||
exit(1);
|
||||
} else {
|
||||
&parser.args[0]
|
||||
};
|
||||
let groupname = args.value_of("GROUP").unwrap();
|
||||
|
||||
let mut sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
{
|
||||
let group = sys_groups.get_mut_by_name(groupname).unwrap_or_else(|| {
|
||||
eprintln!("groupmod: group does not exist: {}", groupname);
|
||||
exit(1);
|
||||
});
|
||||
let group = sys_groups
|
||||
.get_mut_by_name(groupname)
|
||||
.unwrap_or_else(|| {
|
||||
eprintln!("groupmod: group not found: {}", groupname);
|
||||
exit(1);
|
||||
});
|
||||
|
||||
//TODO: Update user's primary GID, if gid is used as such
|
||||
if let Some(gid) = parser.get_opt("gid") {
|
||||
if let Some(gid) = args.value_of("GID") {
|
||||
let gid = gid.parse::<usize>().unwrap_or_exit(1);
|
||||
group.gid = gid;
|
||||
} else if parser.found("gid") {
|
||||
eprintln!("groupmod: no gid found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if let Some(name) = parser.get_opt("name") {
|
||||
group.group = name;
|
||||
} else if parser.found("name") {
|
||||
eprintln!("groupmod: no name found");
|
||||
exit(1);
|
||||
if let Some(name) = args.value_of("NAME") {
|
||||
group.group = name.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+54
-117
@@ -1,20 +1,16 @@
|
||||
extern crate arg_parser;
|
||||
#![deny(warnings)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate redox_users;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::hash::Hash;
|
||||
use std::env;
|
||||
use std::io::{self, Write, Stderr, StdoutLock};
|
||||
use std::process::exit;
|
||||
|
||||
use extra::io::fail;
|
||||
use extra::option::OptionalExt;
|
||||
use arg_parser::{ArgParser, Param};
|
||||
use redox_users::{get_egid, get_gid, get_euid, get_uid, AllUsers, AllGroups};
|
||||
|
||||
const HELP_INFO: &'static str = "Try ‘id --help’ for more information.\n";
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{id} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{id} */ r#"
|
||||
NAME
|
||||
id - display user identity
|
||||
|
||||
@@ -29,202 +25,143 @@ DESCRIPTION
|
||||
the calling process, to the standard output.
|
||||
|
||||
OPTIONS
|
||||
-G
|
||||
-G, --groups
|
||||
Display the different group IDs (effective and real) as white-space
|
||||
separated numbers, in no particular order.
|
||||
|
||||
-g
|
||||
-g, --group
|
||||
Display the effective group ID as a number.
|
||||
|
||||
-n Display the name of the user or group ID for the -g and -u options
|
||||
-n, --name
|
||||
Display the name of the user or group ID for the -g and -u options
|
||||
instead of the number.
|
||||
|
||||
-u
|
||||
-u, --user
|
||||
Display the effective user ID as a number.
|
||||
|
||||
-a
|
||||
Ignored for compatibility with other id implementations.
|
||||
|
||||
-r
|
||||
-r, --real
|
||||
Display the real ID for the -g and -u options instead of the effective ID.
|
||||
|
||||
-h
|
||||
--help
|
||||
Display this help and exit.
|
||||
|
||||
EXIT STATUS
|
||||
The whoami utility exits 0 on success, and >0 if an error occurs.
|
||||
-h, --help
|
||||
Display help and exit.
|
||||
|
||||
AUTHOR
|
||||
Written by Jose Narvaez.
|
||||
"#; /* @MANEND */
|
||||
|
||||
pub fn main() {
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
let mut stderr = io::stderr();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_flag(&["a"])
|
||||
.add_flag(&["G"])
|
||||
.add_flag(&["g"])
|
||||
.add_flag(&["u"])
|
||||
.add_flag(&["n"])
|
||||
.add_flag(&["r"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
print_msg(MAN_PAGE, &mut stdout, &mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Unrecognized flags
|
||||
if let Err(err) = parser.found_invalid() {
|
||||
stderr.write_all(err.as_bytes()).try(&mut stderr);
|
||||
print_msg(HELP_INFO, &mut stdout, &mut stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let groups = AllGroups::new().unwrap_or_exit(1);
|
||||
let users = AllUsers::new().unwrap_or_exit(1);
|
||||
let args = clap_app!(id =>
|
||||
(author: "Jose Narvaez")
|
||||
(about: "Get user and group information about the current user")
|
||||
(@arg IGNORE: -a "Ignored for compatibility with other impls of id")
|
||||
(@arg GROUPS: -G --groups conflicts_with[selector modifier] "Display current user's real and effective group id's")
|
||||
(@group selector =>
|
||||
(@arg GROUP: -g --group "Display current user's effective group id")
|
||||
(@arg USER: -u --user "Display the effective userid")
|
||||
)
|
||||
(@group modifier =>
|
||||
(@arg NAME: -n --name requires[selector] "Display names of groups/users instead of ids (use with -g or -u)")
|
||||
(@arg REAL: -r --real requires[selector] "Display real id's instead of effective ids (use with -g and -u)")
|
||||
)
|
||||
).get_matches();
|
||||
|
||||
// Display the different group IDs (effective and real)
|
||||
// as white-space separated numbers, in no particular order.
|
||||
if parser.found(&'G') {
|
||||
if any_of_found(&parser, &[&'g', &'u']) {
|
||||
let msg = "id: -G option must be used without others\n";
|
||||
print_msg(msg, &mut stdout, &mut stderr);
|
||||
print_msg(HELP_INFO, &mut stdout, &mut stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if args.is_present("GROUPS") {
|
||||
let egid = get_egid().unwrap_or_exit(1);
|
||||
|
||||
let gid = get_gid().unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{} {}\n", egid, gid), &mut stdout, &mut stderr);
|
||||
println!("{} {}", egid, gid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Check if people passed both -g -u which are mutually exclusive
|
||||
if parser.found(&'u') && parser.found(&'g') {
|
||||
let msg = "id: specify either -u or -g but not both\n";
|
||||
print_msg(msg, &mut stdout, &mut stderr);
|
||||
print_msg(HELP_INFO, &mut stdout, &mut stderr);
|
||||
exit(1);
|
||||
}
|
||||
}*/
|
||||
|
||||
// Display effective/real process user ID UNIX user name
|
||||
if parser.found(&'u') && parser.found(&'n') {
|
||||
if args.is_present("USER") && args.is_present("NAME") {
|
||||
// Did they pass -r? F so, we show the real
|
||||
let uid_result = if parser.found(&'r') {
|
||||
let uid = if args.is_present("REAL") {
|
||||
get_uid()
|
||||
} else {
|
||||
get_euid()
|
||||
};
|
||||
|
||||
let uid = uid_result.unwrap_or_exit(1);
|
||||
}.unwrap_or_exit(1);
|
||||
|
||||
let users = AllUsers::new().unwrap_or_exit(1);
|
||||
let user = users.get_by_id(uid).unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{}\n", user.user), &mut stdout, &mut stderr);
|
||||
println!("{}", user.user);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display real user ID
|
||||
if parser.found(&'u') && parser.found(&'r') {
|
||||
if args.is_present("USER") && args.is_present("REAL") {
|
||||
let uid = get_uid().unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{}\n", uid), &mut stdout, &mut stderr);
|
||||
println!("{}", uid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display effective user ID
|
||||
if parser.found(&'u') {
|
||||
if args.is_present("USER") {
|
||||
let euid = get_euid().unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{}\n", euid), &mut stdout, &mut stderr);
|
||||
println!("{}", euid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display effective/real process group ID UNIX group name
|
||||
if parser.found(&'g') && parser.found(&'n') {
|
||||
if args.is_present("GROUP") && args.is_present("NAME") {
|
||||
// Did they pass -r? If so we show the real one
|
||||
let gid_result = if parser.found(&'r') {
|
||||
let gid = if args.is_present("REAL") {
|
||||
get_gid()
|
||||
} else {
|
||||
get_egid()
|
||||
};
|
||||
|
||||
let gid = gid_result.unwrap_or_exit(1);
|
||||
}.unwrap_or_exit(1);
|
||||
|
||||
let groups = AllGroups::new().unwrap_or_exit(1);
|
||||
let group = groups.get_by_id(gid).unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{}\n", group.group), &mut stdout, &mut stderr);
|
||||
println!("{}", group.group);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display the real group ID
|
||||
if parser.found(&'g') && parser.found(&'r') {
|
||||
if args.is_present("GROUP") && args.is_present("REAL") {
|
||||
let gid = get_gid().unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{}\n", gid), &mut stdout, &mut stderr);
|
||||
println!("{}", gid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display effective group ID
|
||||
if parser.found(&'g') {
|
||||
if args.is_present("GROUP") {
|
||||
let egid = get_egid().unwrap_or_exit(1);
|
||||
|
||||
print_msg(&format!("{}\n", egid), &mut stdout, &mut stderr);
|
||||
println!("{}", egid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// -n does not apply if there is no -u or -g
|
||||
if parser.found(&'n') && none_of_found(&parser, &[&'u', &'g']) {
|
||||
let msg = "id: the -n option must be used with either -u or -g\n";
|
||||
fail(msg, &mut stderr);
|
||||
}
|
||||
|
||||
// -r does not apply if there is no -u or -g
|
||||
if parser.found(&'r') && none_of_found(&parser, &[&'u', &'g']) {
|
||||
let msg = "id: the -r option must be used with either -u or -g\n";
|
||||
fail(msg, &mut stderr);
|
||||
}
|
||||
|
||||
// We get everything we can and show
|
||||
let euid = get_euid().unwrap_or_exit(1);
|
||||
|
||||
let egid = get_egid().unwrap_or_exit(1);
|
||||
|
||||
let users = AllUsers::new().unwrap_or_exit(1);
|
||||
let groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
let user = users.get_by_id(euid).unwrap_or_exit(1);
|
||||
|
||||
let group = groups.get_by_id(egid).unwrap_or_exit(1);
|
||||
|
||||
let msg = format!("uid={}({}) gid={}({})\n", euid, user.user, egid, group.group);
|
||||
print_msg(&msg, &mut stdout, &mut stderr);
|
||||
println!("uid={}({}) gid={}({})", euid, user.user, egid, group.group);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
pub fn any_of_found<P: Hash + Eq + ?Sized>(parser: &ArgParser, flags: &[&P]) -> bool
|
||||
where Param: Borrow<P>
|
||||
{
|
||||
for flag in flags {
|
||||
if parser.found(*flag) { return true }
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn none_of_found<P: Hash + Eq + ?Sized>(parser: &ArgParser, flags: &[&P]) -> bool
|
||||
where Param: Borrow<P>
|
||||
{
|
||||
!any_of_found(parser, flags)
|
||||
}
|
||||
|
||||
fn print_msg(msg: &str, stdout: &mut StdoutLock, stderr: &mut Stderr) {
|
||||
stdout.write_all(msg.as_bytes()).try(stderr);
|
||||
stdout.flush().try(stderr);
|
||||
}
|
||||
|
||||
+22
-28
@@ -1,25 +1,25 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate termion;
|
||||
extern crate redox_users;
|
||||
|
||||
use std::{env, io};
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use termion::input::TermRead;
|
||||
use redox_users::{get_uid, AllUsers};
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{passwd} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{passwd} */ r#"
|
||||
NAME
|
||||
passwd - modify a user's password
|
||||
|
||||
SYNOPSIS
|
||||
passwd [ user ]
|
||||
passwd [ LOGIN ]
|
||||
passwd [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -49,35 +49,29 @@ fn main() {
|
||||
let mut stdout = stdout.lock();
|
||||
let mut stderr = io::stderr();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
let args = clap_app!(passwd =>
|
||||
(author: "Jeremy Soller, Jose Narvaez")
|
||||
(about: "Set user passwords")
|
||||
(@arg LOGIN: "Apply to login. Sets password for current user if not supplied")
|
||||
(@arg LOCK: -l --lock "Lock the password for an account (no login)")
|
||||
).get_matches();
|
||||
|
||||
let uid = get_uid().unwrap_or_exit(1);
|
||||
let mut users = AllUsers::new().unwrap_or_exit(1);
|
||||
|
||||
{
|
||||
let user = if parser.args.is_empty() {
|
||||
users.get_mut_by_id(uid).unwrap_or_else(|| {
|
||||
eprintln!("passwd: you do not exist");
|
||||
exit(1);
|
||||
})
|
||||
} else {
|
||||
let username = &parser.args[0];
|
||||
users.get_mut_by_name(username).unwrap_or_else(|| {
|
||||
eprintln!("passwd: user does not exist: {}", username);
|
||||
exit(1);
|
||||
})
|
||||
let user = match args.value_of("LOGIN") {
|
||||
Some(login) => users.get_mut_by_name(login).unwrap_or_else(|| {
|
||||
eprintln!("passwd: user does not exist: {}", login);
|
||||
exit(1);
|
||||
}),
|
||||
None => users.get_mut_by_id(uid).unwrap_or_else(|| {
|
||||
eprintln!("passwd: you do not exist");
|
||||
exit(1);
|
||||
})
|
||||
};
|
||||
|
||||
if parser.found("lock") {
|
||||
if args.is_present("LOCK") {
|
||||
user.unset_passwd();
|
||||
} else if user.uid == uid || uid == 0 {
|
||||
let msg = format!("changing password for '{}' \n", user.user);
|
||||
@@ -87,7 +81,7 @@ fn main() {
|
||||
let mut verified = false;
|
||||
if user.is_passwd_blank() {
|
||||
verified = true;
|
||||
} else if user.is_passwd_unset() {
|
||||
} else if user.is_passwd_unset() && uid != 0 {
|
||||
verified = false;
|
||||
} else if user.uid == uid || uid != 0 {
|
||||
stdout.write_all(b"current password: ").try(&mut stderr);
|
||||
|
||||
+12
-20
@@ -1,23 +1,22 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate termion;
|
||||
extern crate redox_users;
|
||||
extern crate userutils;
|
||||
|
||||
use std::env;
|
||||
use std::io::{self, Write};
|
||||
use std::process::exit;
|
||||
use std::str;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use termion::input::TermRead;
|
||||
use redox_users::{get_uid, AllUsers};
|
||||
use userutils::spawn_shell;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{su} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{su} */ r#"
|
||||
NAME
|
||||
su - substitute user identity
|
||||
|
||||
@@ -31,8 +30,7 @@ DESCRIPTION
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
-h, --help
|
||||
Display this help and exit.
|
||||
|
||||
AUTHOR
|
||||
@@ -46,21 +44,15 @@ pub fn main() {
|
||||
let mut stdout = stdout.lock();
|
||||
let mut stderr = io::stderr();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
let args = clap_app!(su =>
|
||||
(author: "Jeremy Soller, Jose Narvaez")
|
||||
(about: "substitue user identity")
|
||||
(@arg LOGIN: "Login as LOGIN. Default is \'root\'")
|
||||
).get_matches();
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
write!(stdout, "{}", MAN_PAGE).unwrap_or_exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let target_user = if parser.args.is_empty() {
|
||||
String::from("root")
|
||||
} else {
|
||||
parser.args[0].to_string()
|
||||
};
|
||||
let target_user = args
|
||||
.value_of("LOGIN")
|
||||
.unwrap_or("root");
|
||||
|
||||
let uid = get_uid().unwrap_or_exit(1);
|
||||
|
||||
|
||||
+112
-143
@@ -1,21 +1,19 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate syscall;
|
||||
extern crate redox_users;
|
||||
extern crate userutils;
|
||||
|
||||
use std::{env, io};
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use redox_users::{AllGroups, AllUsers};
|
||||
use userutils::create_user_dir;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{useradd} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{useradd} */ r#"
|
||||
NAME
|
||||
useradd - add a new user
|
||||
|
||||
@@ -75,168 +73,139 @@ OPTIONS
|
||||
AUTHORS
|
||||
Written by Wesley Hershberger.
|
||||
"#; /* @MANEND */
|
||||
const DEFAULT_SHELL: &'static str = "/bin/ion";
|
||||
const DEFAULT_HOME: &'static str = "/home";
|
||||
const DEFAULT_SHELL: &'static str = "file:/bin/ion";
|
||||
const DEFAULT_HOME: &'static str = "file:/home";
|
||||
const DEFAULT_NO_GROUP: &'static str = "nobody";
|
||||
|
||||
fn main() {
|
||||
let mut stdout = io::stdout();
|
||||
let args = clap_app!(useradd =>
|
||||
(author: "Wesley Hershberger")
|
||||
(about: "Add users based on the system's redox_users backend")
|
||||
(@arg LOGIN:
|
||||
+required
|
||||
"Add user LOGIN")
|
||||
(@arg COMMENT:
|
||||
-c --comment
|
||||
+takes_value
|
||||
"Set user description (GECOS field)")
|
||||
(@arg HOME_DIR:
|
||||
-d --("home-dir")
|
||||
+takes_value
|
||||
"Set LOGIN's home dir to HOME_DIR (does not create directory)")
|
||||
(@arg CREATE_HOME:
|
||||
-m --("create-home")
|
||||
"Create the user's home directory")
|
||||
(@arg SHELL:
|
||||
-s --shell
|
||||
+takes_value
|
||||
"Set user's default login shell")
|
||||
(@arg GID:
|
||||
-g --gid
|
||||
+takes_value
|
||||
"Set LOGIN's primary group id. Positive integer and must not be in use.")
|
||||
(@arg NO_USER_GROUP:
|
||||
-N --("no-user-group")
|
||||
conflicts_with[GID]
|
||||
"Do not create primary user group (set gid to 99, \"nobody\")")
|
||||
(@arg UID:
|
||||
-u --uid
|
||||
+takes_value
|
||||
"Set LOGIN's user id. Positive ineger and must not be in use.")
|
||||
).get_matches();
|
||||
|
||||
let mut parser = ArgParser::new(8)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_opt("c", "comment")
|
||||
.add_opt("d", "home-dir")
|
||||
.add_opt("g", "gid")
|
||||
.add_flag(&["m", "create-home"])
|
||||
.add_flag(&["N", "no-user-group"])
|
||||
.add_opt("s", "shell")
|
||||
.add_opt("u", "uid");
|
||||
parser.parse(env::args());
|
||||
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
|
||||
stdout.flush().unwrap();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let login = if parser.args.is_empty() {
|
||||
eprintln!("useradd: no login specified");
|
||||
exit(1);
|
||||
} else {
|
||||
&parser.args[0]
|
||||
};
|
||||
// unwrap is safe because of "+required". clap-rs is cool...
|
||||
let login = args.value_of("LOGIN").unwrap();
|
||||
|
||||
let mut sys_users = AllUsers::new().unwrap_or_exit(1);
|
||||
let mut sys_groups;
|
||||
let mut sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
let uid = if parser.found("uid") {
|
||||
match parser.get_opt("uid") {
|
||||
Some(uid) => {
|
||||
let id = uid.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_user) = sys_users.get_by_id(id) {
|
||||
eprintln!("useradd: user already exists with uid: {}", id);
|
||||
let uid = match args.value_of("UID") {
|
||||
Some(uid) => {
|
||||
let id = uid.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_user) = sys_users.get_by_id(id) {
|
||||
eprintln!("useradd: userid already in use: {}", id);
|
||||
exit(1);
|
||||
}
|
||||
id
|
||||
},
|
||||
None => sys_users
|
||||
.get_unique_id()
|
||||
.unwrap_or_else(|| {
|
||||
eprintln!("useradd: no available uid");
|
||||
exit(1);
|
||||
})
|
||||
};
|
||||
|
||||
let gid = if args.is_present("NO_USER_GROUP") {
|
||||
let nobody = sys_groups
|
||||
.get_mut_by_name(DEFAULT_NO_GROUP)
|
||||
.unwrap_or_else(|| {
|
||||
eprintln!("useradd: group not found: {}", DEFAULT_NO_GROUP);
|
||||
exit(1)
|
||||
});
|
||||
nobody.users.push(login.to_string());
|
||||
99
|
||||
} else {
|
||||
let id = match args.value_of("GID") {
|
||||
Some(id) => {
|
||||
let id = id.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_group) = sys_groups.get_by_id(id) {
|
||||
eprintln!("useradd: group already exists with gid: {}", id);
|
||||
exit(1);
|
||||
}
|
||||
id
|
||||
},
|
||||
None => {
|
||||
eprintln!("useradd: missing uid value");
|
||||
None => sys_groups
|
||||
.get_unique_id()
|
||||
.unwrap_or_else(|| {
|
||||
eprintln!("useradd: no available gid");
|
||||
exit(1);
|
||||
})
|
||||
};
|
||||
sys_groups
|
||||
.add_group(login, id, &[login])
|
||||
.unwrap_or_else(|err| {
|
||||
eprintln!("useradd: {}: {}", err, login);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match sys_users.get_unique_id() {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
eprintln!("useradd: no available uid");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//This is a ridiculous mess and could use reworking
|
||||
let gid: usize;
|
||||
if parser.found("no-user-group") {
|
||||
sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
gid = 99;
|
||||
{
|
||||
let nobody = sys_groups.get_mut_by_name("nobody").unwrap_or_else(|| {
|
||||
eprintln!("useradd: group \"nobody\" not found");
|
||||
exit(1)
|
||||
});
|
||||
nobody.users.push(String::from(login.as_str()));
|
||||
}
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
} else {
|
||||
sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
if parser.found("gid") {
|
||||
gid = match parser.get_opt("gid") {
|
||||
Some(gid) => {
|
||||
let id = gid.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_group) = sys_groups.get_by_id(id) {
|
||||
eprintln!("useradd: group already exists with gid: {}", id);
|
||||
exit(1);
|
||||
}
|
||||
id
|
||||
},
|
||||
None => {
|
||||
eprintln!("useradd: missing gid argument");
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
gid = match sys_groups.get_unique_id() {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
eprintln!("useradd: no available gid");
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
}
|
||||
match sys_groups.add_group(login, gid, &[login]) {
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
eprintln!("useradd: error creating group {}: {}", login, err);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
}
|
||||
|
||||
let username = if parser.found("comment") {
|
||||
match parser.get_opt("comment") {
|
||||
Some(user) => user,
|
||||
None => {
|
||||
eprintln!("useradd: invalid argument: -c");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
login.to_owned()
|
||||
id
|
||||
};
|
||||
|
||||
let userhome = if parser.found("home-dir") {
|
||||
match parser.get_opt("home-dir") {
|
||||
Some(dir) => dir,
|
||||
None => {
|
||||
eprintln!("useradd: missing directory argument");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else if parser.found("create-home") {
|
||||
format!("{}/{}", DEFAULT_HOME, login)
|
||||
} else {
|
||||
"/".to_string()
|
||||
};
|
||||
let gecos = args
|
||||
.value_of("COMMENT")
|
||||
.unwrap_or(login);
|
||||
|
||||
let shell = if parser.found("shell") {
|
||||
match parser.get_opt("shell") {
|
||||
Some(sh) => sh,
|
||||
None => {
|
||||
eprintln!("useradd: invalid argument: -s");
|
||||
exit(1);
|
||||
//Ugly way to satisfy the borrow checker...
|
||||
let mut sys_homes = String::from(DEFAULT_HOME);
|
||||
let userhome = args
|
||||
.value_of("HOME_DIR")
|
||||
.unwrap_or_else(|| {
|
||||
if args.is_present("CREATE_HOME") {
|
||||
sys_homes.push_str(&login);
|
||||
sys_homes.as_str()
|
||||
} else {
|
||||
"/"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEFAULT_SHELL.to_string()
|
||||
};
|
||||
});
|
||||
|
||||
match sys_users.add_user(login, uid, gid, username.as_str(), userhome.as_str(), shell.as_str()) {
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
let shell = args
|
||||
.value_of("SHELL")
|
||||
.unwrap_or(DEFAULT_SHELL);
|
||||
|
||||
sys_users
|
||||
.add_user(login, uid, gid, gecos, userhome, shell)
|
||||
.unwrap_or_else(|err| {
|
||||
eprintln!("useradd: {}: {}", err, login);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
println!("Got info: {};{};{};{};{};{}", login, uid, gid, username, userhome, shell);
|
||||
|
||||
// Make sure to try and create the user before we create
|
||||
// Make sure to try and create the user/groups before we create
|
||||
// their home, that way we get a permissions error that makes
|
||||
// more sense
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
sys_users.save().unwrap_or_exit(1);
|
||||
|
||||
if parser.found("create-home") {
|
||||
if args.is_present("CREATE_HOME") {
|
||||
//Shouldn't ever error...
|
||||
let user = sys_users.get_by_id(uid).unwrap_or_exit(1);
|
||||
create_user_dir(user, userhome).unwrap_or_exit(1);
|
||||
|
||||
+11
-24
@@ -1,19 +1,17 @@
|
||||
#[deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate redox_users;
|
||||
|
||||
use std::env;
|
||||
use std::io::{stdout, Write};
|
||||
use std::fs::remove_dir;
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use redox_users::AllUsers;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{userdel} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{userdel} */ r#"
|
||||
NAME
|
||||
userdel - modify system files to delete users
|
||||
|
||||
@@ -43,25 +41,14 @@ AUTHORS
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
let args = clap_app!(userdel =>
|
||||
(author: "Wesley Hershberger")
|
||||
(about: "Removes system users using redox_users")
|
||||
(@arg LOGIN: +required "Remove user LOGIN")
|
||||
(@arg REMOVE: -r --remove "Remove the user's home and all files and directories inside")
|
||||
).get_matches();
|
||||
|
||||
let mut parser = ArgParser::new(9)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_flag(&["r", "remove"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
|
||||
stdout.flush().unwrap();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let login = if parser.args.is_empty() {
|
||||
eprintln!("userdel: no login specified");
|
||||
exit(1);
|
||||
} else {
|
||||
&parser.args[0]
|
||||
};
|
||||
let login = args.value_of("LOGIN").unwrap();
|
||||
|
||||
let mut sys_users = AllUsers::new().unwrap_or_exit(1);
|
||||
{
|
||||
@@ -70,7 +57,7 @@ fn main() {
|
||||
exit(1);
|
||||
});
|
||||
|
||||
if parser.found("remove") {
|
||||
if args.is_present("REMOVE") {
|
||||
remove_dir(&user.home).unwrap_or_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
+75
-77
@@ -1,21 +1,19 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate extra;
|
||||
extern crate redox_users;
|
||||
extern crate userutils;
|
||||
|
||||
use std::env;
|
||||
use std::io::{stdout, Write};
|
||||
use std::fs::{remove_dir, rename};
|
||||
use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use redox_users::{AllGroups, AllUsers};
|
||||
use userutils::create_user_dir;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{usermod} */ r#"
|
||||
const _MAN_PAGE: &'static str = /* @MANSTART{usermod} */ r#"
|
||||
NAME
|
||||
usermod - modify user information
|
||||
|
||||
@@ -76,43 +74,63 @@ AUTHORS
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
let args = clap_app!(usermod =>
|
||||
(author: "Wesley Hershberger")
|
||||
(about: "Modify users according to the system's redox_users backend")
|
||||
(@arg LOGIN:
|
||||
+required
|
||||
"Apply modifications to LOGIN")
|
||||
(@arg COMMENT:
|
||||
-c --comment
|
||||
+takes_value
|
||||
"Set LOGIN's description (GECOS field)")
|
||||
(@arg HOME_DIR:
|
||||
-d --("home-dir")
|
||||
+takes_value
|
||||
"Create and set LOGIN's home directory")
|
||||
(@arg MOVE_HOME:
|
||||
-m --("move-home")
|
||||
requires[HOME_DIR]
|
||||
"Move LOGIN's old home to HOME_DIR (see --home-dir) instead of creating it. Requires -d")
|
||||
(@arg APPEND_GROUPS:
|
||||
-G --("append-groups")
|
||||
+takes_value conflicts_with[SET_GROUPS]
|
||||
"Add user to groups specified (comma separated list, see man page)")
|
||||
(@arg SET_GROUPS:
|
||||
-S --("set-groups")
|
||||
+takes_value conflicts_with[APPEND_GROUPS]
|
||||
"Set LOGIN's groups as specified (truncates existing, see man page)")
|
||||
(@arg GID:
|
||||
-g --gid
|
||||
+takes_value
|
||||
"Set LOGIN's primary group id. Group must exist")
|
||||
(@arg NEW_LOGIN:
|
||||
-l --login
|
||||
+takes_value
|
||||
"Set LOGIN's name to NEW_LOGIN")
|
||||
(@arg SHELL:
|
||||
-s --shell
|
||||
+takes_value
|
||||
"Set LOGIN's default login shell")
|
||||
(@arg UID:
|
||||
-u --uid
|
||||
+takes_value
|
||||
"Set LOGIN's user id. See man page for details")
|
||||
).get_matches();
|
||||
|
||||
let mut parser = ArgParser::new(9)
|
||||
.add_flag(&["h", "help"])
|
||||
.add_flag(&["m", "move-home"])
|
||||
.add_opt("c", "comment")
|
||||
.add_opt("d", "home-dir")
|
||||
.add_opt("G", "groups")
|
||||
.add_opt("g", "gid")
|
||||
.add_opt("l", "login")
|
||||
.add_opt("s", "shell")
|
||||
.add_opt("u", "uid");
|
||||
parser.parse(env::args());
|
||||
|
||||
if parser.found("help") {
|
||||
stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
|
||||
stdout.flush().unwrap();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let login = if parser.args.is_empty() {
|
||||
eprintln!("usermod: no login specified");
|
||||
exit(1);
|
||||
} else {
|
||||
&parser.args[0]
|
||||
};
|
||||
let login = args.value_of("LOGIN").unwrap();
|
||||
|
||||
let mut sys_users = AllUsers::new().unwrap_or_exit(1);
|
||||
let mut sys_groups;
|
||||
|
||||
if parser.found("groups") {
|
||||
//Requires iteration over system groups, which requires additions to redox_users
|
||||
if let Some(_new_groups) = args.value_of("SET_GROUPS") {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
if let Some(new_groups) = args.value_of("APPEND_GROUPS") {
|
||||
sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
let new_groups = parser.get_opt("groups").unwrap_or_else(|| {
|
||||
eprintln!("usermod: no groups found");
|
||||
exit(1);
|
||||
});
|
||||
let new_groups = new_groups.split(',');
|
||||
|
||||
for groupname in new_groups {
|
||||
@@ -120,27 +138,22 @@ fn main() {
|
||||
eprintln!("usermod: no group found: {}", groupname);
|
||||
exit(1);
|
||||
});
|
||||
group.users.push(String::from(login.as_str()));
|
||||
group.users.push(login.to_string());
|
||||
}
|
||||
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
}
|
||||
|
||||
// Nasty to satisfy borrow checker. See line ~174 too
|
||||
let uid = if let Some(uid) = parser.get_opt("uid") {
|
||||
let uid = uid.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_user) = sys_users.get_by_id(uid) {
|
||||
eprintln!("usermod: userid already in use: {}", uid);
|
||||
exit(1);
|
||||
} else {
|
||||
Some(uid)
|
||||
}
|
||||
} else if parser.found("uid") {
|
||||
eprintln!("usermod: no uid found");
|
||||
exit(1);
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let uid = args
|
||||
.value_of("UID")
|
||||
.map(|uid| {
|
||||
let uid = uid.parse::<usize>().unwrap_or_exit(1);
|
||||
if let Some(_user) = sys_users.get_by_id(uid) {
|
||||
eprintln!("usermod: userid already in use: {}", uid);
|
||||
exit(1);
|
||||
}
|
||||
uid
|
||||
});
|
||||
|
||||
{
|
||||
let user = sys_users.get_mut_by_name(&login).unwrap_or_else(|| {
|
||||
@@ -148,46 +161,33 @@ fn main() {
|
||||
exit(1);
|
||||
});
|
||||
|
||||
if let Some(gecos) = parser.get_opt("comment") {
|
||||
user.name = gecos;
|
||||
// If we found it but ^that^ was None, problem
|
||||
} else if parser.found("comment") {
|
||||
eprintln!("usermod: no comment found");
|
||||
exit(1);
|
||||
if let Some(gecos) = args.value_of("COMMENT") {
|
||||
user.name = gecos.to_string();
|
||||
}
|
||||
|
||||
if let Some(new_login) = parser.get_opt("login") {
|
||||
user.user = new_login;
|
||||
} else if parser.found("login") {
|
||||
eprintln!("usermod: no login found");
|
||||
exit(1);
|
||||
if let Some(new_login) = args.value_of("NEW_LOGIN") {
|
||||
user.user = new_login.to_string();
|
||||
}
|
||||
|
||||
if let Some(shell) = parser.get_opt("shell") {
|
||||
user.shell = shell;
|
||||
} else if parser.found("shell") {
|
||||
eprintln!("usermod: no shell found");
|
||||
exit(1);
|
||||
if let Some(shell) = args.value_of("SHELL") {
|
||||
user.shell = shell.to_string();
|
||||
}
|
||||
|
||||
if let Some(home) = parser.get_opt("home-dir") {
|
||||
if parser.found("move-home") {
|
||||
if let Some(home) = args.value_of("HOME_DIR") {
|
||||
if args.is_present("MOVE_HOME") {
|
||||
rename(&user.home, &home).unwrap_or_exit(1);
|
||||
} else {
|
||||
create_user_dir(user, &home).unwrap_or_exit(1);
|
||||
remove_dir(&user.home).unwrap_or_exit(1);
|
||||
}
|
||||
user.home = home;
|
||||
} else if parser.found("home-dir") {
|
||||
eprintln!("usermod: no home dir found");
|
||||
exit(1);
|
||||
user.home = home.to_string();
|
||||
}
|
||||
|
||||
if let Some(uid) = uid {
|
||||
user.uid = uid;
|
||||
}
|
||||
|
||||
if let Some(gid) = parser.get_opt("gid") {
|
||||
if let Some(gid) = args.value_of("GID") {
|
||||
sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
let gid = gid.parse::<usize>().unwrap_or_exit(1);
|
||||
|
||||
@@ -195,10 +195,8 @@ fn main() {
|
||||
user.gid = gid;
|
||||
} else {
|
||||
eprintln!("usermod: no group found for id: {}", gid);
|
||||
exit(1);
|
||||
}
|
||||
} else if parser.found("gid") {
|
||||
eprintln!("usermod: no gid found");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user