Merge pull request #28 from MggMuggins/master
Implement usermod, groupmod, userdel, groupdel; Fix passwd and useradd
This commit is contained in:
Generated
+1
-1
@@ -158,7 +158,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/redox-os/users.git#70b8a69ce6588693d05f3500b481c2620c1ee824"
|
||||
source = "git+https://github.com/redox-os/users.git#0fc602398887533c947b3f428e9fe0037f829478"
|
||||
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)",
|
||||
|
||||
+16
@@ -14,6 +14,14 @@ path = "src/bin/getty.rs"
|
||||
name = "groupadd"
|
||||
path = "src/bin/groupadd.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "groupdel"
|
||||
path = "src/bin/groupdel.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "groupmod"
|
||||
path = "src/bin/groupmod.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "login"
|
||||
path = "src/bin/login.rs"
|
||||
@@ -34,6 +42,14 @@ path = "src/bin/sudo.rs"
|
||||
name = "useradd"
|
||||
path = "src/bin/useradd.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "userdel"
|
||||
path = "src/bin/userdel.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "usermod"
|
||||
path = "src/bin/usermod.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "whoami"
|
||||
path = "src/bin/whoami.rs"
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#[deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
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#"
|
||||
NAME
|
||||
groupdel - modify system files to delete groups
|
||||
|
||||
SYNOPSYS
|
||||
groupdel [ options ] LOGIN
|
||||
groupdel [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
groupdel removes groups from whatever backend is employed by
|
||||
the system's redox_users.
|
||||
|
||||
Note that you should not remove a primary user group before
|
||||
removing the user. It is also generally wise not to remove
|
||||
groups that still own files on the system.
|
||||
|
||||
OPTIONS
|
||||
-h, --help
|
||||
Print this help page and exit.
|
||||
|
||||
AUTHORS
|
||||
Wesley Hershberger.
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
|
||||
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 mut sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
|
||||
sys_groups.remove_by_name(group.to_string()).unwrap_or_exit(1);
|
||||
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#[deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
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#"
|
||||
NAME
|
||||
groupmod - modify group information
|
||||
|
||||
SYNOPSYS
|
||||
groupmod [ options ] GROUP
|
||||
groupmod [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
groupmod modifies a user group GROUP in the system's
|
||||
redox_users backend.
|
||||
|
||||
OPTIONS
|
||||
-h, --help
|
||||
Print this help page and exit.
|
||||
|
||||
-g, --gid GID
|
||||
Change GROUP's group id. GID must be a non-negative
|
||||
decimal integer.
|
||||
|
||||
Files with GROUP's old gid will not be updated.
|
||||
|
||||
User's who use the old gid as their primary gid will
|
||||
also not be updated. This is a TODO and will change.
|
||||
|
||||
-n, --name NAME
|
||||
The name of the group will be set to NAME
|
||||
|
||||
AUTHORS
|
||||
Wesley Hershberger.
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
|
||||
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 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);
|
||||
});
|
||||
|
||||
//TODO: Update user's primary GID, if gid is used as such
|
||||
if let Some(gid) = parser.get_opt("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);
|
||||
}
|
||||
}
|
||||
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
}
|
||||
+21
-6
@@ -29,10 +29,15 @@ DESCRIPTION
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
-h, --help
|
||||
Display this help and exit.
|
||||
|
||||
-l, --lock
|
||||
Lock the password of the named account. This changes the stored password
|
||||
hash so that it matches no encrypted value ("!")
|
||||
|
||||
Users with locked passwords are not allowed to change their password.
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller, Jose Narvaez.
|
||||
"#; /* @MANEND */
|
||||
@@ -60,13 +65,21 @@ fn main() {
|
||||
|
||||
{
|
||||
let user = if parser.args.is_empty() {
|
||||
users.get_mut_by_id(uid).unwrap_or_exit(1)
|
||||
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_exit(1)
|
||||
users.get_mut_by_name(username).unwrap_or_else(|| {
|
||||
eprintln!("passwd: user does not exist: {}", username);
|
||||
exit(1);
|
||||
})
|
||||
};
|
||||
|
||||
if user.uid == uid || uid == 0 {
|
||||
|
||||
if parser.found("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);
|
||||
@@ -74,6 +87,8 @@ fn main() {
|
||||
let mut verified = false;
|
||||
if user.is_passwd_blank() {
|
||||
verified = true;
|
||||
} else if user.is_passwd_unset() {
|
||||
verified = false;
|
||||
} else if user.uid == uid || uid != 0 {
|
||||
stdout.write_all(b"current password: ").try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);
|
||||
|
||||
+44
-18
@@ -4,6 +4,7 @@ extern crate arg_parser;
|
||||
extern crate extra;
|
||||
extern crate syscall;
|
||||
extern crate redox_users;
|
||||
extern crate userutils;
|
||||
|
||||
use std::{env, io};
|
||||
use std::io::Write;
|
||||
@@ -11,9 +12,8 @@ use std::process::exit;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use syscall::call::{open, fchmod, fchown};
|
||||
use syscall::flag::{O_CREAT, O_DIRECTORY, O_CLOEXEC};
|
||||
use redox_users::{AllGroups, AllUsers};
|
||||
use userutils::create_user_dir;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{useradd} */ r#"
|
||||
NAME
|
||||
@@ -40,15 +40,16 @@ OPTIONS
|
||||
|
||||
-c, --comment
|
||||
Any text string, usually used as the user's full name.
|
||||
Historically known as the GECOS field
|
||||
|
||||
-d, --home-dir HOME_DIR
|
||||
The new user will be created with HOME_DIR as their home
|
||||
directory. The default value is LOGIN prepended with "/home".
|
||||
This flag DOES NOT create the home directory. See --create-home.
|
||||
directory. The default value is LOGIN prepended with "/home/".
|
||||
This flag DOES NOT create the home directory. See --create-home
|
||||
|
||||
-g, --gid GID
|
||||
The group id to use for the default login group. This value must
|
||||
not be in use and must be non-negative. The default is to pick the
|
||||
The group id to use when creating the default login group. This value
|
||||
must not be in use and must be non-negative. The default is to pick the
|
||||
smallest available group id between values defined in redox_users.
|
||||
|
||||
-m, --create-home
|
||||
@@ -56,14 +57,14 @@ OPTIONS
|
||||
|
||||
This option is not enabled by default. This option must be specified
|
||||
for a home directory to be created. If not set, the user's home dir is
|
||||
set to "/".
|
||||
set to "/"
|
||||
|
||||
-N, --no-user-group
|
||||
Do not attempt to create the user's user group. Instead, the groupid
|
||||
is set to 99 (should be the "nobody" group).
|
||||
is set to 99 ("nobody"). -N and -g are mutually exclusive.
|
||||
|
||||
-s, --shell SHELL
|
||||
The path to the user's default login shell. If left blank, the
|
||||
The path to the user's default login shell. If not specified, the
|
||||
default shell is set as "/bin/ion"
|
||||
|
||||
-u, --uid UID
|
||||
@@ -76,7 +77,6 @@ AUTHORS
|
||||
"#; /* @MANEND */
|
||||
const DEFAULT_SHELL: &'static str = "/bin/ion";
|
||||
const DEFAULT_HOME: &'static str = "/home";
|
||||
const DEFAULT_MODE: u16 = 0o700;
|
||||
|
||||
fn main() {
|
||||
let mut stdout = io::stdout();
|
||||
@@ -106,11 +106,18 @@ fn main() {
|
||||
};
|
||||
|
||||
let mut sys_users = AllUsers::new().unwrap_or_exit(1);
|
||||
let mut sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
let mut sys_groups;
|
||||
|
||||
let uid = if parser.found("uid") {
|
||||
match parser.get_opt("uid") {
|
||||
Some(uid) => uid.parse::<usize>().unwrap_or_exit(1),
|
||||
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);
|
||||
exit(1);
|
||||
}
|
||||
id
|
||||
},
|
||||
None => {
|
||||
eprintln!("useradd: missing uid value");
|
||||
exit(1);
|
||||
@@ -129,12 +136,29 @@ fn main() {
|
||||
//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;
|
||||
//TODO: Add this user to the "nobody" group
|
||||
{
|
||||
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) => gid.parse::<usize>().unwrap_or_exit(1),
|
||||
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);
|
||||
@@ -156,6 +180,7 @@ fn main() {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
}
|
||||
|
||||
let username = if parser.found("comment") {
|
||||
@@ -204,15 +229,16 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
println!("Got info: {};{};{};{};{};{}", login, uid, gid, username, userhome, shell);
|
||||
|
||||
// Make sure to try and create the user before we create
|
||||
// their home, that way we get a permissions error that makes
|
||||
// more sense
|
||||
sys_users.save().unwrap_or_exit(1);
|
||||
sys_groups.save().unwrap_or_exit(1);
|
||||
|
||||
if parser.found("create-home") {
|
||||
let fd = open(userhome, O_CREAT | O_DIRECTORY | O_CLOEXEC).unwrap_or_exit(1);
|
||||
fchmod(fd, DEFAULT_MODE).unwrap_or_exit(1);
|
||||
fchown(fd, uid as u32, gid as u32).unwrap_or_exit(1);
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#[deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
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#"
|
||||
NAME
|
||||
userdel - modify system files to delete users
|
||||
|
||||
SYNOPSYS
|
||||
userdel [ options ] LOGIN
|
||||
userdel [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
userdel removes users from whatever backend is employed by
|
||||
the system's redox_users.
|
||||
|
||||
It can also be used to manage removal of home directories.
|
||||
|
||||
This utility does not remove the user from any groups! This is
|
||||
a planned feature and will be implemented at some point.
|
||||
|
||||
OPTIONS
|
||||
-h, --help
|
||||
Print this help page and exit.
|
||||
|
||||
-r, --remove
|
||||
The user's home directory and all files inside will be
|
||||
removed.
|
||||
|
||||
AUTHORS
|
||||
Wesley Hershberger.
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
|
||||
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 mut sys_users = AllUsers::new().unwrap_or_exit(1);
|
||||
{
|
||||
let user = sys_users.get_by_name(login).unwrap_or_else(|| {
|
||||
eprintln!("userdel: user does not exist: {}", login);
|
||||
exit(1);
|
||||
});
|
||||
|
||||
if parser.found("remove") {
|
||||
remove_dir(&user.home).unwrap_or_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
sys_users.remove_by_name(login.to_string()).unwrap_or_exit(1);
|
||||
|
||||
sys_users.save().unwrap_or_exit(1);
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate arg_parser;
|
||||
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#"
|
||||
NAME
|
||||
usermod - modify user information
|
||||
|
||||
SYNOPSYS
|
||||
usermod [ options ] LOGIN
|
||||
usermod [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
The usermod utility can be used to modify user information.
|
||||
|
||||
This utility uses the redox_users API, so the backend is whatever
|
||||
backend in use on the system for that API at the time.
|
||||
|
||||
See passwd for setting user passwords.
|
||||
|
||||
OPTIONS
|
||||
-h, --help
|
||||
Display this help and exit.
|
||||
|
||||
-c, --comment COMMENT
|
||||
The comment field (or GECOS, historically) for the user. This
|
||||
is typically the full name of the user, although sometimes it
|
||||
includes an e-mail.
|
||||
|
||||
-d, --home-dir HOME_DIR
|
||||
Sets the home directory to HOME_DIR and creates the directory.
|
||||
See -m for move
|
||||
|
||||
-m, --move-home
|
||||
Moves the the user's old home directory into the home directory
|
||||
specified by --home-dir. Has no effect if passed without --home-dir
|
||||
|
||||
-G, --append-groups GROUP[,GROUP, ...]
|
||||
Add this user to GROUP groups. This does not remove the user from
|
||||
any group of which they are already a member.
|
||||
|
||||
-S, --set-groups GROUP[,GROUP, ...]
|
||||
Remove the user from all groups of which they are a part and add
|
||||
them to GROUP groups.
|
||||
|
||||
-g, --gid GID
|
||||
Set the user's primary group id. If the group does not exist,
|
||||
a warning is issued and no changes are applied.
|
||||
|
||||
-l, --login NEW_LOGIN
|
||||
Set the new login name for the user. Must not be in use.
|
||||
|
||||
-s, --shell SHELL
|
||||
Set the user's login shell as SHELL. This must be a full path.
|
||||
|
||||
-u, --uid UID
|
||||
Set the user's user id. If another user's userid is the same as
|
||||
UID, a warning is issued and no changes are applied. Note that
|
||||
changing the value of the user's userid may have unexpected consequences.
|
||||
|
||||
AUTHORS
|
||||
Written by Wesley Hershberger.
|
||||
"#; /* @MANEND */
|
||||
|
||||
fn main() {
|
||||
let mut stdout = stdout();
|
||||
|
||||
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 mut sys_users = AllUsers::new().unwrap_or_exit(1);
|
||||
let mut sys_groups;
|
||||
|
||||
if parser.found("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 {
|
||||
let group = sys_groups.get_mut_by_name(groupname).unwrap_or_else(|| {
|
||||
eprintln!("usermod: no group found: {}", groupname);
|
||||
exit(1);
|
||||
});
|
||||
group.users.push(String::from(login.as_str()));
|
||||
}
|
||||
|
||||
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 user = sys_users.get_mut_by_name(&login).unwrap_or_else(|| {
|
||||
eprintln!("usermod: user \"{}\" not found", login);
|
||||
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(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(shell) = parser.get_opt("shell") {
|
||||
user.shell = shell;
|
||||
} else if parser.found("shell") {
|
||||
eprintln!("usermod: no shell found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if let Some(home) = parser.get_opt("home-dir") {
|
||||
if parser.found("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);
|
||||
}
|
||||
|
||||
if let Some(uid) = uid {
|
||||
user.uid = uid;
|
||||
}
|
||||
|
||||
if let Some(gid) = parser.get_opt("gid") {
|
||||
sys_groups = AllGroups::new().unwrap_or_exit(1);
|
||||
let gid = gid.parse::<usize>().unwrap_or_exit(1);
|
||||
|
||||
if let Some(_group) = sys_groups.get_by_id(gid) {
|
||||
user.gid = gid;
|
||||
} else {
|
||||
eprintln!("usermod: no group found for id: {}", gid);
|
||||
}
|
||||
} else if parser.found("gid") {
|
||||
eprintln!("usermod: no gid found");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
sys_users.save().unwrap_or_exit(1);
|
||||
}
|
||||
+16
@@ -17,10 +17,16 @@
|
||||
//! - `whoami`: Display effective user ID.
|
||||
|
||||
extern crate redox_users;
|
||||
extern crate syscall;
|
||||
|
||||
use std::io::Result;
|
||||
|
||||
use redox_users::User;
|
||||
use syscall::call::{open, fchmod, fchown};
|
||||
use syscall::error::Result as SysResult;
|
||||
use syscall::flag::{O_CREAT, O_DIRECTORY, O_CLOEXEC};
|
||||
|
||||
const DEFAULT_MODE: u16 = 0o700;
|
||||
|
||||
/// Spawns a shell for the given `User`.
|
||||
///
|
||||
@@ -46,3 +52,13 @@ pub fn spawn_shell(user: &User) -> Result<i32> {
|
||||
None => Ok(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn create_user_dir<T>(user: &User, dir: T) -> SysResult<()>
|
||||
where T: AsRef<str> + std::convert::AsRef<[u8]>
|
||||
{
|
||||
let fd = open(dir, O_CREAT | O_DIRECTORY | O_CLOEXEC)?;
|
||||
fchmod(fd, DEFAULT_MODE)?;
|
||||
fchown(fd, user.uid as u32, user.gid as u32)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user