Merge branch 'cleanup' into 'master'

Various cleanups

See merge request redox-os/userutils!50
This commit is contained in:
Jeremy Soller
2025-04-13 20:15:18 +00:00
14 changed files with 187 additions and 221 deletions
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "userutils"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "id"
+6 -24
View File
@@ -1,10 +1,5 @@
#[macro_use]
extern crate clap;
extern crate event;
extern crate extra;
extern crate libredox;
extern crate orbclient;
extern crate redox_termios;
use std::io::{self, ErrorKind, Stderr};
use std::process::{Child, Command, Stdio};
@@ -125,13 +120,10 @@ pub fn getpty(columns: u32, lines: u32) -> (RawFd, String) {
.expect("getty: failed to create PTY");
if let Ok(winsize_fd) = redox::dup(master, b"winsize") {
let _ = redox::write(
winsize_fd,
&redox_termios::Winsize {
ws_row: lines as u16,
ws_col: columns as u16,
},
);
let _ = redox::write(winsize_fd, &redox_termios::Winsize {
ws_row: lines as u16,
ws_col: columns as u16,
});
let _ = redox::close(winsize_fd);
}
@@ -142,12 +134,7 @@ pub fn getpty(columns: u32, lines: u32) -> (RawFd, String) {
})
}
fn daemon(
tty_fd: RawFd,
clear: bool,
contain: bool,
stderr: &mut Stderr,
) {
fn daemon(tty_fd: RawFd, clear: bool, contain: bool, stderr: &mut Stderr) {
let (columns, lines) = {
let mut path = [0; 4096];
if let Ok(count) = redox::fpath(tty_fd as usize, &mut path) {
@@ -203,12 +190,7 @@ fn daemon(
match command.spawn() {
Ok(mut process) => {
handle(
&mut event_queue,
tty_fd,
master_fd,
&mut process,
);
handle(&mut event_queue, tty_fd, master_fd, &mut process);
}
Err(err) => fail(&format!("getty: failed to execute login: {}", err), stderr),
}
+9 -9
View File
@@ -1,7 +1,5 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
use extra::option::OptionalExt;
@@ -9,7 +7,8 @@ use std::process::exit;
use redox_users::{All, AllGroups, Config, Error, GroupBuilder};
const _MAN_PAGE: &'static str = /* @MANSTART{groupadd} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{groupadd} */
r#"
NAME
groupadd - add a user group
@@ -46,7 +45,8 @@ fn main() {
(@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 +takes_value "Group id. Positive integer and must not be in use")
).get_matches();
)
.get_matches();
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
@@ -60,11 +60,11 @@ fn main() {
exit(1);
}
id
},
}
None => sys_groups.get_unique_id().unwrap_or_else(|| {
eprintln!("groupadd: no available gid");
exit(1);
})
eprintln!("groupadd: no available gid");
exit(1);
}),
};
let group = GroupBuilder::new(groupname).gid(gid);
@@ -72,7 +72,7 @@ fn main() {
Ok(_) => (),
Err(Error::GroupAlreadyExists) if args.is_present("FORCE") => {
exit(0);
},
}
Err(err) => {
eprintln!("groupadd: {}", err);
exit(1);
+4 -4
View File
@@ -1,12 +1,11 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
use extra::option::OptionalExt;
use redox_users::{All, AllGroups, Config};
const _MAN_PAGE: &'static str = /* @MANSTART{groupdel} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{groupdel} */
r#"
NAME
groupdel - modify system files to delete groups
@@ -35,7 +34,8 @@ fn main() {
(author: "Wesley Hershberger")
(about: "Removes a group from the system using redox_users")
(@arg GROUP: +required "Removes group GROUP")
).get_matches();
)
.get_matches();
let group = matches.value_of("GROUP").unwrap();
+10 -11
View File
@@ -1,14 +1,13 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config};
const _MAN_PAGE: &'static str = /* @MANSTART{groupmod} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{groupmod} */
r#"
NAME
groupmod - modify group information
@@ -47,23 +46,23 @@ fn main() {
(@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();
)
.get_matches();
let groupname = args.value_of("GROUP").unwrap();
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
{
let group = sys_groups
.get_mut_by_name(groupname)
.unwrap_or_else(|| {
eprintln!("groupmod: group not found: {}", groupname);
exit(1);
});
let group = sys_groups.get_mut_by_name(groupname).unwrap_or_else(|| {
eprintln!("groupmod: group not found: {}", groupname);
exit(1);
});
if let Some(gid) = args.value_of("GID") {
let gid = gid.parse::<usize>().unwrap_or_exit(1);
// Update users
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
for user in sys_users.iter_mut() {
if user.gid == group.gid {
user.gid = gid;
+13 -12
View File
@@ -1,15 +1,14 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
use std::env::args;
use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{get_egid, get_gid, get_euid, get_uid, All, AllUsers, AllGroups, Config};
use redox_users::{All, AllGroups, AllUsers, Config, get_egid, get_euid, get_gid, get_uid};
const _MAN_PAGE: &'static str = /* @MANSTART{id} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{id} */
r#"
NAME
id - display user identity
@@ -69,7 +68,7 @@ pub fn main() {
let args = match &*args().nth(0).unwrap_or(String::new()) {
"whoami" => app.get_matches_from(["id", "-un"].iter()),
_ => app.get_matches()
_ => app.get_matches(),
};
// Display the different group IDs (effective and real)
@@ -81,16 +80,17 @@ pub fn main() {
println!("{} {}", egid, gid);
exit(0);
}
}
// Display effective/real process user ID UNIX user name
if args.is_present("USER") && args.is_present("NAME") {
// Display effective/real process user ID UNIX user name
if args.is_present("USER") && args.is_present("NAME") {
// Did they pass -r? If so, we show the real
let uid = if args.is_present("REAL") {
get_uid()
} else {
get_euid()
}.unwrap_or_exit(1);
}
.unwrap_or_exit(1);
let users = AllUsers::basic(Config::default()).unwrap_or_exit(1);
let user = users.get_by_id(uid).unwrap_or_exit(1);
@@ -115,14 +115,15 @@ pub fn main() {
exit(0);
}
// Display effective/real process group ID UNIX group name
if args.is_present("GROUP") && args.is_present("NAME") {
// Display effective/real process group ID UNIX group name
if args.is_present("GROUP") && args.is_present("NAME") {
// Did they pass -r? If so we show the real one
let gid = if args.is_present("REAL") {
get_gid()
} else {
get_egid()
}.unwrap_or_exit(1);
}
.unwrap_or_exit(1);
let groups = AllGroups::new(Config::default()).unwrap_or_exit(1);
let group = groups.get_by_id(gid).unwrap_or_exit(1);
+26 -27
View File
@@ -1,21 +1,17 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate liner;
extern crate termion;
extern crate redox_users;
extern crate userutils;
use std::fs::File;
use std::io::{self, Write};
use std::str;
use extra::option::OptionalExt;
use termion::input::TermRead;
use redox_users::{All, AllUsers, Config};
use termion::input::TermRead;
use userutils::spawn_shell;
const _MAN_PAGE: &'static str = /* @MANSTART{login} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{login} */
r#"
NAME
login - log into the computer
@@ -44,11 +40,12 @@ pub fn main() {
let _args = clap_app!(login =>
(author: "Jeremy Soller, Jose Narvaez")
(about: "Login as a user")
).get_matches();
)
.get_matches();
if let Ok(mut issue) = File::open(ISSUE_FILE) {
io::copy(&mut issue, &mut stdout).try(&mut stderr);
stdout.flush().try(&mut stderr);
io::copy(&mut issue, &mut stdout).r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
}
loop {
@@ -56,9 +53,9 @@ pub fn main() {
.read_line(
liner::Prompt::from("\x1B[1mredox login:\x1B[0m "),
None,
&mut liner::BasicCompleter::new(Vec::<String>::new())
&mut liner::BasicCompleter::new(Vec::<String>::new()),
)
.try(&mut stderr);
.r#try(&mut stderr);
if !user.is_empty() {
let stdin = io::stdin();
@@ -67,32 +64,34 @@ pub fn main() {
match sys_users.get_by_name(user) {
None => {
stdout.write(b"\nLogin incorrect\n").try(&mut stderr);
stdout.write(b"\n").try(&mut stderr);
stdout.flush().try(&mut stderr);
stdout.write(b"\nLogin incorrect\n").r#try(&mut stderr);
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
continue;
},
}
Some(user) => {
if user.is_passwd_blank() {
if let Ok(mut motd) = File::open(MOTD_FILE) {
io::copy(&mut motd, &mut stdout).try(&mut stderr);
stdout.flush().try(&mut stderr);
io::copy(&mut motd, &mut stdout).r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
}
spawn_shell(user).unwrap_or_exit(1);
break;
}
stdout.write_all(b"\x1B[1mpassword:\x1B[0m ").try(&mut stderr);
stdout.flush().try(&mut stderr);
if let Some(password) = stdin.read_passwd(&mut stdout).try(&mut stderr) {
stdout.write(b"\n").try(&mut stderr);
stdout.flush().try(&mut stderr);
stdout
.write_all(b"\x1B[1mpassword:\x1B[0m ")
.r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if let Some(password) = stdin.read_passwd(&mut stdout).r#try(&mut stderr) {
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if user.verify_passwd(&password) {
if let Ok(mut motd) = File::open(MOTD_FILE) {
io::copy(&mut motd, &mut stdout).try(&mut stderr);
stdout.flush().try(&mut stderr);
io::copy(&mut motd, &mut stdout).r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
}
spawn_shell(user).unwrap_or_exit(1);
@@ -102,8 +101,8 @@ pub fn main() {
}
}
} else {
stdout.write(b"\n").try(&mut stderr);
stdout.flush().try(&mut stderr);
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
}
}
}
+32 -28
View File
@@ -1,18 +1,16 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate termion;
extern crate redox_users;
use std::io;
use std::io::Write;
use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{All, AllUsers, Config, get_uid};
use termion::input::TermRead;
use redox_users::{get_uid, All, AllUsers, Config};
const _MAN_PAGE: &'static str = /* @MANSTART{passwd} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{passwd} */
r#"
NAME
passwd - modify a user's password
@@ -52,7 +50,8 @@ fn main() {
(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();
)
.get_matches();
let uid = get_uid().unwrap_or_exit(1);
let mut users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
@@ -60,21 +59,21 @@ fn main() {
{
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);
}),
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);
})
eprintln!("passwd: you do not exist");
exit(1);
}),
};
if args.is_present("LOCK") {
user.unset_passwd();
} else if user.uid == uid || uid == 0 {
let msg = format!("changing password for '{}' \n", user.user);
stdout.write_all(&msg.as_bytes()).try(&mut stderr);
stdout.flush().try(&mut stderr);
stdout.write_all(&msg.as_bytes()).r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
let mut verified = false;
if user.is_passwd_blank() {
@@ -82,12 +81,12 @@ fn main() {
} 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);
stdout.flush().try(&mut stderr);
stdout.write_all(b"current password: ").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if let Some(password) = stdin.read_passwd(&mut stdout).try(&mut stderr) {
stdout.write(b"\n").try(&mut stderr);
stdout.flush().try(&mut stderr);
if let Some(password) = stdin.read_passwd(&mut stdout).r#try(&mut stderr) {
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
verified = user.verify_passwd(&password)
}
@@ -96,16 +95,18 @@ fn main() {
}
if verified {
stdout.write_all(b"new password: ").try(&mut stderr);
stdout.flush().try(&mut stderr);
stdout.write_all(b"new password: ").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if let Some(new_password) = stdin.read_passwd(&mut stdout).try(&mut stderr) {
stdout.write(b"\nconfirm password: ").try(&mut stderr);
stdout.flush().try(&mut stderr);
if let Some(new_password) = stdin.read_passwd(&mut stdout).r#try(&mut stderr) {
stdout.write(b"\nconfirm password: ").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if let Some(confirm_password) = stdin.read_passwd(&mut stdout).try(&mut stderr) {
stdout.write(b"\n").try(&mut stderr);
stdout.flush().try(&mut stderr);
if let Some(confirm_password) =
stdin.read_passwd(&mut stdout).r#try(&mut stderr)
{
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if new_password == confirm_password {
user.set_passwd(&new_password).unwrap_or_exit(1);
@@ -126,7 +127,10 @@ fn main() {
exit(1);
}
} else {
eprintln!("passwd: you do not have permission to set the password of '{}'", user.user);
eprintln!(
"passwd: you do not have permission to set the password of '{}'",
user.user
);
exit(1);
}
}
+10 -11
View File
@@ -1,20 +1,17 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate termion;
extern crate redox_users;
extern crate userutils;
use std::io::{self, Write};
use std::process::exit;
use std::str;
use extra::option::OptionalExt;
use redox_users::{All, AllUsers, Config, get_uid};
use termion::input::TermRead;
use redox_users::{get_uid, All, AllUsers, Config};
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
@@ -46,11 +43,10 @@ pub fn main() {
(author: "Jeremy Soller, Jose Narvaez")
(about: "substitue user identity")
(@arg LOGIN: "Login as LOGIN. Default is \'root\'")
).get_matches();
)
.get_matches();
let target_user = args
.value_of("LOGIN")
.unwrap_or("root");
let target_user = args.value_of("LOGIN").unwrap_or("root");
let uid = get_uid().unwrap_or_exit(1);
@@ -67,7 +63,10 @@ pub fn main() {
stdout.flush().unwrap_or_exit(1);
// Read the password, reading an empty string if CTRL-d is specified
let password = stdin.read_passwd(&mut stdout).try(&mut stderr).unwrap_or(String::new());
let password = stdin
.read_passwd(&mut stdout)
.r#try(&mut stderr)
.unwrap_or(String::new());
writeln!(stderr, "\n").unwrap_or_exit(1);
+6 -16
View File
@@ -1,14 +1,10 @@
extern crate extra;
extern crate redox_users;
extern crate termion;
use std::env;
use std::io::{self, Write};
use std::os::unix::process::CommandExt;
use std::process::{exit, Command};
use std::process::{Command, exit};
use extra::option::OptionalExt;
use redox_users::{get_uid, All, AllGroups, AllUsers, Config};
use redox_users::{All, AllGroups, AllUsers, Config, get_uid};
use termion::input::TermRead;
const MAX_ATTEMPTS: u16 = 3;
@@ -35,11 +31,6 @@ AUTHOR
"#; /* @MANEND */
pub fn main() {
let stdin = io::stdin();
let mut stdin = stdin.lock();
let stdout = io::stdout();
let mut stdout = stdout.lock();
let mut args = env::args().skip(1);
let cmd = args.next().unwrap_or_else(|| {
eprintln!("sudo: no command provided");
@@ -77,12 +68,11 @@ pub fn main() {
loop {
print!("[sudo] password for {}: ", user.user);
let _ = stdout.flush();
let _ = io::stdout().flush();
match stdin.read_passwd(&mut stdout).unwrap() {
match io::stdin().read_passwd(&mut io::stdout()).unwrap() {
Some(password) => {
write!(stdout, "\n").unwrap();
let _ = stdout.flush();
println!();
if user.verify_passwd(&password) {
break;
@@ -95,7 +85,7 @@ pub fn main() {
}
}
None => {
write!(stdout, "\n").unwrap();
println!();
exit(1);
}
}
+37 -44
View File
@@ -1,8 +1,5 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
extern crate userutils;
use std::process::exit;
@@ -10,7 +7,8 @@ use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config, GroupBuilder, UserBuilder};
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
@@ -108,12 +106,14 @@ fn main() {
-u --uid
+takes_value
"Set LOGIN's user id. Positive ineger and must not be in use.")
).get_matches();
)
.get_matches();
// unwrap is safe because of "+required". clap-rs is cool...
let login = args.value_of("LOGIN").unwrap();
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
let uid = match args.value_of("UID") {
@@ -124,13 +124,11 @@ fn main() {
exit(1);
}
id
},
None => sys_users
.get_unique_id()
.unwrap_or_else(|| {
eprintln!("useradd: no available uid");
exit(1);
})
}
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") {
@@ -151,13 +149,11 @@ fn main() {
exit(1);
}
id
},
None => sys_groups
.get_unique_id()
.unwrap_or_else(|| {
eprintln!("useradd: no available gid");
exit(1);
})
}
None => sys_groups.get_unique_id().unwrap_or_else(|| {
eprintln!("useradd: no available gid");
exit(1);
}),
};
sys_groups
.add_group(GroupBuilder::new(login).gid(id).user(login))
@@ -168,35 +164,32 @@ fn main() {
id
};
let gecos = args
.value_of("COMMENT")
.unwrap_or(login);
let gecos = args.value_of("COMMENT").unwrap_or(login);
//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("/");
sys_homes.push_str(&login);
sys_homes.as_str()
} else {
"/"
}
});
let userhome = args.value_of("HOME_DIR").unwrap_or_else(|| {
if args.is_present("CREATE_HOME") {
sys_homes.push_str("/");
sys_homes.push_str(&login);
sys_homes.as_str()
} else {
"/"
}
});
let shell = args
.value_of("SHELL")
.unwrap_or(DEFAULT_SHELL);
let shell = args.value_of("SHELL").unwrap_or(DEFAULT_SHELL);
let user = UserBuilder::new(login).uid(uid).gid(gid).name(gecos).home(userhome).shell(shell);
sys_users
.add_user(user)
.unwrap_or_else(|err| {
eprintln!("useradd: {}: {}", err, login);
exit(1);
});
let user = UserBuilder::new(login)
.uid(uid)
.gid(gid)
.name(gecos)
.home(userhome)
.shell(shell);
sys_users.add_user(user).unwrap_or_else(|err| {
eprintln!("useradd: {}: {}", err, login);
exit(1);
});
// Make sure to try and create the user/groups before we create
// their home, that way we get a permissions error that makes
+6 -6
View File
@@ -1,8 +1,5 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
extern crate userutils;
use std::fs::remove_dir;
use std::process::exit;
@@ -11,7 +8,8 @@ use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config};
use userutils::AllGroupsExt;
const _MAN_PAGE: &'static str = /* @MANSTART{userdel} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{userdel} */
r#"
NAME
userdel - modify system files to delete users
@@ -44,11 +42,13 @@ fn main() {
(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();
)
.get_matches();
let login = args.value_of("LOGIN").unwrap();
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
{
sys_groups.remove_user_from_all_groups(login);
+19 -18
View File
@@ -1,17 +1,15 @@
#[macro_use]
extern crate clap;
extern crate extra;
extern crate redox_users;
extern crate userutils;
use std::fs::{remove_dir, rename};
use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config};
use userutils::{create_user_dir, AllGroupsExt};
use userutils::{AllGroupsExt, create_user_dir};
const _MAN_PAGE: &'static str = /* @MANSTART{usermod} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{usermod} */
r#"
NAME
usermod - modify user information
@@ -119,32 +117,35 @@ fn main() {
let login = args.value_of("LOGIN").unwrap();
//TODO: Does not always need shadowfile access
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_groups;
if let Some(new_groups) = args.value_of("SET_GROUPS") {
sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
sys_groups.remove_user_from_all_groups(login);
sys_groups.add_user_to_groups(login, new_groups.split(',').collect()).unwrap_or_exit(1);
sys_groups
.add_user_to_groups(login, new_groups.split(',').collect())
.unwrap_or_exit(1);
sys_groups.save().unwrap_or_exit(1);
}
if let Some(new_groups) = args.value_of("APPEND_GROUPS") {
sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
sys_groups.add_user_to_groups(login, new_groups.split(',').collect()).unwrap_or_exit(1);
sys_groups
.add_user_to_groups(login, new_groups.split(',').collect())
.unwrap_or_exit(1);
sys_groups.save().unwrap_or_exit(1);
}
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 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(|| {
+8 -11
View File
@@ -16,15 +16,12 @@
//! - `sudo`: Enables users to execute a command as another user.
//! - `whoami`: Display effective user ID.
extern crate redox_users;
extern crate libredox;
use std::io::Result as IoResult;
use redox_users::{auth, All, AllGroups, Result, User, Error};
use libredox::call::{open, fchown};
use libredox::call::{fchown, open};
use libredox::error::Result as SysResult;
use libredox::flag::{O_CREAT, O_DIRECTORY, O_CLOEXEC};
use libredox::flag::{O_CLOEXEC, O_CREAT, O_DIRECTORY};
use redox_users::{All, AllGroups, Error, Result, User, auth};
const DEFAULT_MODE: u16 = 0o700;
@@ -41,7 +38,7 @@ impl AllGroupsExt for AllGroups {
for groupname in new_groups {
let group = match self.get_mut_by_name(groupname) {
Some(group) => group,
None => return Err(Error::UserNotFound)
None => return Err(Error::UserNotFound),
};
group.users.push(login.to_string());
}
@@ -51,8 +48,7 @@ impl AllGroupsExt for AllGroups {
/// Remove a user from all groups of which they are a member
fn remove_user_from_all_groups(&mut self, login: &str) {
for group in self.iter_mut() {
let op_pos = group.users.iter()
.position(|username| username == login );
let op_pos = group.users.iter().position(|username| username == login);
if let Some(indx) = op_pos {
group.users.remove(indx);
}
@@ -81,13 +77,14 @@ pub fn spawn_shell(user: &User<auth::Full>) -> IoResult<i32> {
let mut child = command.spawn()?;
match child.wait()?.code() {
Some(code) => Ok(code),
None => Ok(1)
None => Ok(1),
}
}
/// Creates a directory with 700 user:user permissions
pub fn create_user_dir<T>(user: &User<auth::Full>, dir: T) -> SysResult<()>
where T: AsRef<str> + std::convert::AsRef<[u8]>
where
T: AsRef<str> + std::convert::AsRef<[u8]>,
{
let fd = open(dir, O_CREAT | O_DIRECTORY | O_CLOEXEC, DEFAULT_MODE)?;
fchown(fd, user.uid as u32, user.gid as u32)?;