Commit fba0c70a authored by SamwiseFilmore's avatar SamwiseFilmore

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.
parent e997bdd1
[[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"
......
#![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);
}
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 clear = !args.is_present("NO_CLEAR");
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),
......
#![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 gid = if let Some(gid) = parser.get_opt("gid") {
let gid = gid.parse::<usize>().unwrap_or_exit(1);
let groupname = args.value_of("GROUP").unwrap();
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) => {
......
#[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 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 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 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);
......
#[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();
}
}
......
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