Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion m4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ path = "src/main.rs"
[dependencies]
clap.workspace = true
env_logger = "0.11"
errno = "0.3"
errno.workspace = true
libc.workspace = true
log = "0.4"
nom = "7.1"
Expand Down
2 changes: 2 additions & 0 deletions plib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ license = "MIT"
repository = "https://github.com/rustcoreutils/posixutils-rs.git"

[dependencies]
cfg-if = "1.0"
libc.workspace = true
errno.workspace = true

[lib]
doctest = false
38 changes: 38 additions & 0 deletions plib/src/ipc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use libc::ipc_perm;

#[cfg(not(target_os = "macos"))]
pub fn get_key_from_msqid_ds(
#[cfg_attr(target_env = "musl", allow(unused_variables))] msgid_ds_ref: &libc::msqid_ds,
) -> i32 {
// Prevent accidental shadowing by using a block
{
cfg_if::cfg_if! {
if #[cfg(target_env = "musl")] {
0 // TODO: What placeholder value should go here?
} else {
msgid_ds_ref.msg_perm.__key // Ensure the correct field name for your system
}
}
}
}

pub fn get_key_from_ipc_perm(
#[cfg_attr(target_env = "musl", allow(unused_variables))] ipc_perm_ref: &ipc_perm,
) -> i32 {
// Prevent accidental shadowing by using a block
{
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
ipc_perm_ref._key // Check for the correct field name on your system
} else {
cfg_if::cfg_if! {
if #[cfg(target_env = "musl")] {
0 // TODO: What placeholder value should go here?
} else {
ipc_perm_ref.__key // Check for the correct field name on your system
}
}
}
}
}
}
4 changes: 4 additions & 0 deletions plib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
pub mod curuser;
pub mod group;
pub mod io;
pub mod ipc;
pub mod lzw;
pub mod modestr;
pub mod platform;
pub mod priority;
pub mod sccsfile;
pub mod terminal;
pub mod testing;
pub mod utmpx;

Expand Down
83 changes: 83 additions & 0 deletions plib/src/platform.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// TODO
// Avoid restating local alias names
cfg_if::cfg_if! {
if #[cfg(target_env = "musl")] {
// https://git.musl-libc.org/cgit/musl/tree/include/utmpx.h?id=1e7f0fcd7ff2096904fd93a2ee6d12a2392be392
pub const EMPTY: libc::c_short = 0_i16;
pub const RUN_LVL: libc::c_short = 1_i16;
pub const BOOT_TIME: libc::c_short = 2_i16;
pub const NEW_TIME: libc::c_short = 3_i16;
pub const OLD_TIME: libc::c_short = 4_i16;
pub const INIT_PROCESS: libc::c_short = 5_i16;
pub const LOGIN_PROCESS: libc::c_short = 6_i16;
pub const USER_PROCESS: libc::c_short = 7_i16;
pub const DEAD_PROCESS: libc::c_short = 8_i16;

// Remove when https://github.com/rust-lang/libc/issues/3190 is resolved
// https://github.com/rust-lang/libc/commit/e3caaf6b0ea08ae294e25a861022c256a7535ec4#diff-5822a2981791fb0bb7689a921abdc2133cc73116ee125eabefad3a9374056b7a
extern "C" {
pub fn getutxent() -> *mut libc::utmpx;
pub fn getutxid(ut: *const libc::utmpx) -> *mut libc::utmpx;
pub fn getutxline(ut: *const libc::utmpx) -> *mut libc::utmpx;
pub fn pututxline(ut: *const libc::utmpx) -> *mut libc::utmpx;
pub fn setutxent();
pub fn endutxent();
}

type LocalPIoctlOp = libc::c_int;
type LocalPPriorityWhichT = libc::c_int;
} else {
pub use libc::{
endutxent,
getutxent,
setutxent,
BOOT_TIME,
DEAD_PROCESS,
EMPTY,
INIT_PROCESS,
LOGIN_PROCESS,
NEW_TIME,
OLD_TIME,
RUN_LVL,
USER_PROCESS,
};

cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
type LocalPPriorityWhichT = libc::c_int;
} else {
type LocalPPriorityWhichT = libc::__priority_which_t;
}
}

type LocalPIoctlOp = libc::c_ulong;
}
}

// Constants taken from:
// https://docs.rs/term_size/0.3.2/src/term_size/platform/unix.rs.html#5-19
pub(crate) const P_WINSIZE_REQUEST_CODE: LocalPIoctlOp = ({
#[cfg(any(target_os = "linux", target_os = "android"))]
{
0x5413
}

#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
{
0x40087468
}

#[cfg(target_os = "solaris")]
{
0x5468
}
}) as LocalPIoctlOp;

pub(crate) type PPriorityWhichT = LocalPPriorityWhichT;
29 changes: 29 additions & 0 deletions plib/src/priority.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::platform::PPriorityWhichT;
use std::io;

pub fn getpriority(which: u32, id: u32) -> io::Result<i32> {
errno::set_errno(errno::Errno(0));

let res = unsafe { libc::getpriority(which as PPriorityWhichT, id) };

let errno_res = errno::errno().0;
if errno_res == 0 {
Ok(res)
} else {
let e = io::Error::from_raw_os_error(errno_res);
eprintln!("getpriority: {e}");
Err(e)
}
}

pub fn setpriority(which: u32, id: u32, prio: i32) -> io::Result<()> {
let res = unsafe { libc::setpriority(which as PPriorityWhichT, id, prio) };

if res < 0 {
let e = io::Error::last_os_error();
eprintln!("setpriority: {e}");
Err(e)
} else {
Ok(())
}
}
32 changes: 32 additions & 0 deletions plib/src/terminal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use crate::platform::P_WINSIZE_REQUEST_CODE;
use std::mem::MaybeUninit;

pub fn get_terminal_width() -> usize {
// COLUMNS is usually automatically set and it even changes when the
// terminal window is resized.
if let Ok(s) = std::env::var("COLUMNS") {
if let Ok(num_columns) = s.parse() {
return num_columns;
}
}

// Fallback to manually querying via `ioctl`.
unsafe {
let mut winsize: MaybeUninit<libc::winsize> = MaybeUninit::zeroed();
let ret = libc::ioctl(
libc::STDOUT_FILENO,
P_WINSIZE_REQUEST_CODE,
winsize.as_mut_ptr(),
);

// We're only interested in stdout here unlike `term_size::dimensions`
// so we won't query further if the first `ioctl` call fails.
if ret == 0 {
let winsize = winsize.assume_init();
return winsize.ws_col as usize;
}
}

// Historical default terminal width is 80
80
}
20 changes: 10 additions & 10 deletions plib/src/utmpx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// SPDX-License-Identifier: MIT
//

use libc::{endutxent, getutxent, setutxent};
use crate::platform::{self, endutxent, getutxent, setutxent};
use std::ffi::CStr;

#[derive(Debug)]
Expand All @@ -23,15 +23,15 @@ pub struct Utmpx {

pub fn ut_type_str(typ: libc::c_short) -> &'static str {
match typ {
libc::BOOT_TIME => "BOOT_TIME",
libc::DEAD_PROCESS => "DEAD_PROCESS",
libc::EMPTY => "EMPTY",
libc::INIT_PROCESS => "INIT_PROCESS",
libc::LOGIN_PROCESS => "LOGIN_PROCESS",
libc::NEW_TIME => "NEW_TIME",
libc::OLD_TIME => "OLD_TIME",
libc::RUN_LVL => "RUN_LVL",
libc::USER_PROCESS => "USER_PROCESS",
platform::BOOT_TIME => "BOOT_TIME",
platform::DEAD_PROCESS => "DEAD_PROCESS",
platform::EMPTY => "EMPTY",
platform::INIT_PROCESS => "INIT_PROCESS",
platform::LOGIN_PROCESS => "LOGIN_PROCESS",
platform::NEW_TIME => "NEW_TIME",
platform::OLD_TIME => "OLD_TIME",
platform::RUN_LVL => "RUN_LVL",
platform::USER_PROCESS => "USER_PROCESS",

_ => "(unknown)",
}
Expand Down
1 change: 0 additions & 1 deletion process/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ clap.workspace = true
gettext-rs.workspace = true
libc.workspace = true
atty.workspace = true
errno = "0.3"
dirs = "5.0"

[[bin]]
Expand Down
42 changes: 3 additions & 39 deletions process/renice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
//

use clap::Parser;
use errno::{errno, set_errno};
use gettextrs::{bind_textdomain_codeset, setlocale, textdomain, LocaleCategory};
use libc::{getpwnam, passwd};
use plib::priority::{getpriority, setpriority};
use plib::PROJECT_NAME;
use std::ffi::CString;
use std::io;

const PRIO_MIN: i32 = -20;
const PRIO_MAX: i32 = 20;
Expand Down Expand Up @@ -75,41 +74,6 @@ fn parse_id(which: u32, input: &str) -> Result<u32, &'static str> {
}
}

fn xgetpriority(which: u32, id: u32) -> io::Result<i32> {
set_errno(errno::Errno(0));

#[cfg(not(target_os = "macos"))]
let res = unsafe { libc::getpriority(which, id) };

#[cfg(target_os = "macos")]
let res = unsafe { libc::getpriority(which as i32, id) };

let errno_res = errno().0;
if errno_res == 0 {
Ok(res)
} else {
let e = io::Error::from_raw_os_error(errno_res);
eprintln!("getpriority: {}", e);
Err(e)
}
}

fn xsetpriority(which: u32, id: u32, prio: i32) -> io::Result<()> {
#[cfg(not(target_os = "macos"))]
let res = unsafe { libc::setpriority(which, id, prio) };

#[cfg(target_os = "macos")]
let res = unsafe { libc::setpriority(which as i32, id, prio) };

if res < 0 {
let e = io::Error::last_os_error();
eprintln!("setpriority: {}", e);
Err(e)
} else {
Ok(())
}
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
// parse command line arguments
let args = Args::parse();
Expand All @@ -133,13 +97,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let id = parse_id(which, &args.id)?;

// get current priority
let prio = xgetpriority(which, id)?;
let prio = getpriority(which, id)?;

// adjust priority based on user input
let newprio = (prio + args.niceval).clamp(PRIO_MIN, PRIO_MAX);

// attempt to set new priority
xsetpriority(which, id, newprio)?;
setpriority(which, id, newprio)?;

Ok(())
}
Loading