Implement usermod, groupmod, userdel, groupdel; Fix passwd and useradd
Here I've implemented the remainder of the core user utilities present on most unix systems. They aren't particularly pretty, but they do work for the most part. Note that for some reason attempting to move the home directory of a user via usermod -m does not work. Also removing user's that have been deleted from groups is not yet implemented, nor is updating /etc/passwd when a group id is changed. Note that redox_users as used by Cargo.lock as of this commit is broken, and may not work properly. If redox-os/users#11 is merged, cargo update should fix.
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