refactor: split library to mutiple modules
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
@@ -107,7 +107,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "luad"
|
name = "luad"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"libc",
|
"libc",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "luad"
|
name = "luad"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
1301
src/fcgi.rs
Normal file
1301
src/fcgi.rs
Normal file
File diff suppressed because it is too large
Load Diff
1713
src/lib.rs
1713
src/lib.rs
File diff suppressed because it is too large
Load Diff
151
src/logs.rs
Normal file
151
src/logs.rs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
use crate::{APP_VERSION, DAEMON_NAME, ERR};
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::fmt::Arguments;
|
||||||
|
|
||||||
|
/// LOG_MASK is used to create the priority mask in setlogmask
|
||||||
|
/// For a mask UPTO specified
|
||||||
|
/// used with [Priority]
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use luad::LOG_UPTO;
|
||||||
|
/// LOG_UPTO!(LogLevel::ERROR)
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! LOG_UPTO
|
||||||
|
{
|
||||||
|
($($arg:tt)*) => (
|
||||||
|
((1 << (($($arg)*) + 1)) - 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for error log helper
|
||||||
|
///
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! INFO {
|
||||||
|
($($args:tt)*) => ({
|
||||||
|
let prefix = format!(":info@[{}:{}]: ",file!(), line!());
|
||||||
|
let _ = crate::LOG::log(&prefix[..], &crate::LogLevel::INFO, format_args!($($args)*));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for warning log helper
|
||||||
|
///
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! WARN {
|
||||||
|
($($args:tt)*) => ({
|
||||||
|
let prefix = format!(":warning@[{}:{}]: ",file!(), line!());
|
||||||
|
let _ = crate::LOG::log(&prefix[..], &crate::LogLevel::WARN, format_args!($($args)*));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for info log helper
|
||||||
|
///
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! ERROR {
|
||||||
|
($($args:tt)*) => ({
|
||||||
|
let prefix = format!(":error@[{}:{}]: ",file!(), line!());
|
||||||
|
let _ = crate::LOG::log(&prefix[..], &crate::LogLevel::ERROR, format_args!($($args)*));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for info log debug
|
||||||
|
///
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! DEBUG {
|
||||||
|
($($args:tt)*) => ({
|
||||||
|
let prefix = format!(":debug@[{}:{}]: ",file!(), line!());
|
||||||
|
let _ = crate::LOG::log(&prefix[..], &crate::LogLevel::DEBUG, format_args!($($args)*));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Different Logging levels for `LOG`
|
||||||
|
pub enum LogLevel {
|
||||||
|
/// Error conditions
|
||||||
|
ERROR,
|
||||||
|
/// Normal, but significant, condition
|
||||||
|
INFO,
|
||||||
|
/// Warning conditions
|
||||||
|
WARN,
|
||||||
|
/// Debugs message
|
||||||
|
DEBUG,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Log struct wrapper
|
||||||
|
///
|
||||||
|
pub struct LOG {}
|
||||||
|
|
||||||
|
impl LOG {
|
||||||
|
/// Init the system log
|
||||||
|
///
|
||||||
|
/// This should be called only once in the entire lifetime
|
||||||
|
/// of the program, the returned LOG instance should
|
||||||
|
/// be keep alive during the lifetime of the program (the main function).
|
||||||
|
/// When it is dropped, the connection to the system log will be
|
||||||
|
/// closed automatically
|
||||||
|
#[must_use]
|
||||||
|
pub fn init_log() -> Self {
|
||||||
|
// connect to the system log
|
||||||
|
unsafe {
|
||||||
|
libc::openlog(
|
||||||
|
std::ptr::null(),
|
||||||
|
libc::LOG_CONS | libc::LOG_PID | libc::LOG_NDELAY,
|
||||||
|
libc::LOG_DAEMON,
|
||||||
|
);
|
||||||
|
let _ = libc::setlogmask(LOG_UPTO!(libc::LOG_NOTICE));
|
||||||
|
}
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
/// Enable the Log debug
|
||||||
|
///
|
||||||
|
pub fn enable_debug() {
|
||||||
|
unsafe {
|
||||||
|
let _ = libc::setlogmask(LOG_UPTO!(libc::LOG_INFO));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper function that log error or info message to the
|
||||||
|
/// connected syslog server
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `prefix` - Prefix of the log message
|
||||||
|
/// * `level` - Log level
|
||||||
|
/// * `args` - Arguments object representing a format string and its arguments
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// * `std error` - All errors related to formatted and C string manipulation
|
||||||
|
pub fn log(prefix: &str, level: &LogLevel, args: Arguments<'_>) -> Result<(), std::io::Error> {
|
||||||
|
use std::fmt::Write;
|
||||||
|
let sysloglevel = match level {
|
||||||
|
LogLevel::ERROR => libc::LOG_ERR,
|
||||||
|
LogLevel::WARN => libc::LOG_WARNING,
|
||||||
|
LogLevel::INFO => libc::LOG_NOTICE,
|
||||||
|
_ => libc::LOG_INFO,
|
||||||
|
};
|
||||||
|
let mut output = String::new();
|
||||||
|
if output.write_fmt(args).is_err() {
|
||||||
|
return Err(ERR!("Unable to create format string from arguments"));
|
||||||
|
}
|
||||||
|
let log_fmt = format!("{}(v{}){}%s\n", DAEMON_NAME, APP_VERSION, prefix);
|
||||||
|
let fmt = CString::new(log_fmt.as_bytes())?;
|
||||||
|
let c_msg = CString::new(output.as_bytes())?;
|
||||||
|
unsafe {
|
||||||
|
libc::syslog(sysloglevel, fmt.as_ptr(), c_msg.as_ptr());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for LOG {
|
||||||
|
/// The connection to the syslog will be closed
|
||||||
|
/// automatically when the log object is drop
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Close the current connection to the system logger
|
||||||
|
unsafe {
|
||||||
|
libc::closelog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
240
src/luapi.rs
Normal file
240
src/luapi.rs
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use crate::{ERR, ERROR};
|
||||||
|
use mlua::{prelude::*, Variadic};
|
||||||
|
/// Magic number for lua slice structure
|
||||||
|
const LUA_SLICE_MAGIC: usize = 0x8AD73B9F;
|
||||||
|
|
||||||
|
/// Convert a Lua Variadic to vector of bytes
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `values` (`mlua::Variadic<LuaValue>`) - input variadic
|
||||||
|
/// - `bin_only` (`bool`) - if true only convert Binary data
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `Result<Vec<u8>, std::io::Error>`
|
||||||
|
///
|
||||||
|
pub fn vec_from_variadic(
|
||||||
|
values: Variadic<LuaValue>,
|
||||||
|
bin_only: bool,
|
||||||
|
) -> Result<Vec<u8>, std::io::Error> {
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
let error = ERR!("Unsupported data type");
|
||||||
|
for value in values {
|
||||||
|
match &value {
|
||||||
|
LuaNil => {}
|
||||||
|
LuaValue::Boolean(v) => {
|
||||||
|
if bin_only {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
output.extend(v.to_string().as_bytes());
|
||||||
|
}
|
||||||
|
LuaValue::Integer(v) => {
|
||||||
|
if bin_only {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
output.extend(v.to_string().as_bytes());
|
||||||
|
}
|
||||||
|
LuaValue::Number(v) => {
|
||||||
|
if bin_only {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
output.extend(v.to_string().as_bytes());
|
||||||
|
}
|
||||||
|
LuaValue::String(v) => {
|
||||||
|
output.extend(v.as_bytes());
|
||||||
|
}
|
||||||
|
LuaValue::LightUserData(_)
|
||||||
|
| LuaValue::Table(_)
|
||||||
|
| LuaValue::Function(_)
|
||||||
|
| LuaValue::Thread(_) => {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
LuaValue::UserData(v) => {
|
||||||
|
if v.is::<LuabyteArray>() {
|
||||||
|
let arr = v
|
||||||
|
.borrow::<LuabyteArray>()
|
||||||
|
.map_err(|e| ERR!(e.to_string()))?;
|
||||||
|
output.extend(&arr.0);
|
||||||
|
} else {
|
||||||
|
let st = value.to_pointer() as *const LuaSlice;
|
||||||
|
if unsafe { (*st).magic } != LUA_SLICE_MAGIC {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
let data_slice = unsafe { std::slice::from_raw_parts((*st).data, (*st).len) };
|
||||||
|
output.extend(data_slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LuaValue::Error(e) => {
|
||||||
|
return Err(ERR!(e.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new empty LuaByteArray
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `_` (`&mlua::Lua`) - a Lua VM
|
||||||
|
/// - `size` (`usize`) - data size
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `LuaResult<LuabyteArray>`
|
||||||
|
pub fn lua_new_bytes(_: &Lua, size: usize) -> LuaResult<LuabyteArray> {
|
||||||
|
let arr = LuabyteArray(vec![0; size]);
|
||||||
|
Ok(arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a LuaByteArray from a binary slice
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `_` (`&mlua::Lua`) - Lua VM
|
||||||
|
/// - `value` (`mlua::Value`) - LuaSlice value
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `LuaResult<LuabyteArray>`
|
||||||
|
pub fn lua_new_from_slice(_: &Lua, value: mlua::Value) -> LuaResult<LuabyteArray> {
|
||||||
|
let st = value.to_pointer() as *const LuaSlice;
|
||||||
|
if unsafe { (*st).magic } != LUA_SLICE_MAGIC {
|
||||||
|
return Err(mlua::Error::external(ERR!("Unsupported data type")));
|
||||||
|
}
|
||||||
|
let data_slice = unsafe { std::slice::from_raw_parts((*st).data, (*st).len) };
|
||||||
|
Ok(LuabyteArray(data_slice.to_vec()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new LuaByteArray from string
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `_` (`&mlua::Lua`) - Lua VM
|
||||||
|
/// - `string` (`String`) - input string
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `LuaResult<LuabyteArray>`
|
||||||
|
pub fn lua_new_bytes_from_string(_: &Lua, string: String) -> LuaResult<LuabyteArray> {
|
||||||
|
let arr = LuabyteArray(string.as_bytes().to_vec());
|
||||||
|
Ok(arr)
|
||||||
|
}
|
||||||
|
/// Custom LuaByteArray
|
||||||
|
///
|
||||||
|
/// # Fields
|
||||||
|
///
|
||||||
|
/// - `field_0` (`Vec<u8>`) - raw data
|
||||||
|
///
|
||||||
|
pub struct LuabyteArray(pub Vec<u8>);
|
||||||
|
|
||||||
|
impl mlua::UserData for LuabyteArray {
|
||||||
|
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_method("size", |_, this: &LuabyteArray, ()| Ok(this.0.len()));
|
||||||
|
|
||||||
|
methods.add_method("into", |_, this: &LuabyteArray, value: mlua::Value| {
|
||||||
|
let st = value.to_pointer() as *mut LuaSlice;
|
||||||
|
if unsafe { (*st).magic } != LUA_SLICE_MAGIC {
|
||||||
|
return Err(mlua::Error::external(ERR!("Unsupported data type")));
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
(*st).data = this.0.as_ptr() as *const u8;
|
||||||
|
(*st).len = this.0.len();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_method("fileout", |_, this: &LuabyteArray, path: String| {
|
||||||
|
match std::fs::File::create(&path) {
|
||||||
|
Ok(mut file) => {
|
||||||
|
if let Err(error) = file.write_all(&this.0) {
|
||||||
|
ERROR!("Unable to write byte array to file {}: {}", &path, error);
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
ERROR!("Unable open file {}: {}", path, error);
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(1)
|
||||||
|
});
|
||||||
|
methods.add_meta_method(mlua::MetaMethod::Index, |_, this, index: isize| {
|
||||||
|
if index < 1 || index > this.0.len() as isize {
|
||||||
|
let error = ERR!(format!(
|
||||||
|
"Index {} out of bound, array size is {}",
|
||||||
|
index,
|
||||||
|
this.0.len()
|
||||||
|
));
|
||||||
|
ERROR!("{}", error);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
Ok(Some(this.0[index as usize - 1]))
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_meta_method(
|
||||||
|
mlua::MetaMethod::ToString,
|
||||||
|
|_, this, ()| match String::from_utf8(this.0.clone()) {
|
||||||
|
Err(error) => {
|
||||||
|
let err = format!("Unable to convert byte array to string: {}", error);
|
||||||
|
ERROR!("{}", err);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
Ok(string) => Ok(Some(string)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
methods.add_method_mut("extend", |_, this, values: Variadic<mlua::Value>| {
|
||||||
|
let mut output = vec_from_variadic(values, true)
|
||||||
|
.map_err(|e| mlua::Error::external(ERR!(e.to_string())))?;
|
||||||
|
this.0.append(&mut output);
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_meta_method_mut(
|
||||||
|
mlua::MetaMethod::NewIndex,
|
||||||
|
|_, this, (index, value): (isize, u8)| {
|
||||||
|
if index < 1 || index > this.0.len() as isize {
|
||||||
|
let error = ERR!(format!(
|
||||||
|
"Index {} out of bound, array size is {}",
|
||||||
|
index,
|
||||||
|
this.0.len()
|
||||||
|
));
|
||||||
|
ERROR!("{}", error);
|
||||||
|
} else {
|
||||||
|
this.0[index as usize - 1] = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
methods.add_meta_method(mlua::MetaMethod::Len, |_, this, ()| Ok(this.0.len()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LuaSlice
|
||||||
|
///
|
||||||
|
/// # Fields
|
||||||
|
///
|
||||||
|
/// - `magic` (`usize`) - LuaSlice magic number
|
||||||
|
/// - `len` (`usize`) - data size
|
||||||
|
/// - `data` (`*const u8`) - raw data value
|
||||||
|
///
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct LuaSlice {
|
||||||
|
magic: usize,
|
||||||
|
len: usize,
|
||||||
|
data: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// public C API that return LuaSlice magic number
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `usize` - magic number
|
||||||
|
///
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn lua_slice_magic() -> usize {
|
||||||
|
return LUA_SLICE_MAGIC;
|
||||||
|
}
|
||||||
@@ -76,7 +76,7 @@ fn serve(config: &Config) {
|
|||||||
let listener = UnixListener::bind(socket_name.replace("unix:", "")).unwrap();
|
let listener = UnixListener::bind(socket_name.replace("unix:", "")).unwrap();
|
||||||
for client in listener.incoming() {
|
for client in listener.incoming() {
|
||||||
let mut stream = client.unwrap();
|
let mut stream = client.unwrap();
|
||||||
let _ = std::thread::spawn(move || {
|
let _ = thread::spawn(move || {
|
||||||
handle_request(&mut stream);
|
handle_request(&mut stream);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
101
src/utils.rs
Normal file
101
src/utils.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
use crate::{ERR, INFO};
|
||||||
|
use nix;
|
||||||
|
|
||||||
|
/// Drop user privileges
|
||||||
|
///
|
||||||
|
/// This function drop the privileges of the current user
|
||||||
|
/// to another inferior privileges user.
|
||||||
|
/// e.g. drop from root->maint
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `user` - system user name
|
||||||
|
/// * `group` - system group name
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// * `nix::Error` - The error from the nix package
|
||||||
|
pub fn privdrop(useropt: Option<&str>, groupopt: Option<&str>) -> Result<(), nix::Error> {
|
||||||
|
match groupopt {
|
||||||
|
Some(group) => {
|
||||||
|
INFO!("Dropping current process group to {}", group);
|
||||||
|
match nix::unistd::Group::from_name(group)? {
|
||||||
|
Some(group) => nix::unistd::setgid(group.gid),
|
||||||
|
None => Err(nix::Error::last()),
|
||||||
|
}?;
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
match useropt {
|
||||||
|
Some(user) => {
|
||||||
|
INFO!("Dropping current process user to {}", user);
|
||||||
|
match nix::unistd::User::from_name(user)? {
|
||||||
|
Some(user) => nix::unistd::setuid(user.uid),
|
||||||
|
None => Err(nix::Error::last()),
|
||||||
|
}?
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if a file descriptor is an unix socket
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `fd` (`libc::c_int`) - input file descriptor
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `Result<bool, std::io::Error>`
|
||||||
|
///
|
||||||
|
pub fn is_unix_socket(fd: libc::c_int) -> Result<bool, std::io::Error> {
|
||||||
|
unsafe {
|
||||||
|
let mut addr: libc::sockaddr_storage = std::mem::zeroed();
|
||||||
|
let mut addr_len: libc::socklen_t = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
|
||||||
|
let addr_storage: *mut libc::sockaddr_storage = &mut addr;
|
||||||
|
let ret = libc::getsockname(fd, addr_storage as *mut _, &mut addr_len);
|
||||||
|
if ret != 0 {
|
||||||
|
return Err(ERR!(format!("Unable to check socket: {}", fd)));
|
||||||
|
}
|
||||||
|
Ok(i32::from(addr.ss_family) == libc::AF_UNIX)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Utility function to catch common signal that
|
||||||
|
/// cause the program to exit
|
||||||
|
///
|
||||||
|
/// Signals catched: SIGABRT, SIGINT, SIGTERM, SIGQUIT
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `f` - callback function that will be called when a signal is trapped
|
||||||
|
pub fn on_exit(f: fn(n: i32) -> ()) {
|
||||||
|
unsafe {
|
||||||
|
let _ = libc::signal(libc::SIGPIPE, libc::SIG_IGN);
|
||||||
|
let _ = libc::signal(libc::SIGABRT, (f as *const std::ffi::c_void) as usize);
|
||||||
|
let _ = libc::signal(libc::SIGINT, (f as *const std::ffi::c_void) as usize);
|
||||||
|
let _ = libc::signal(libc::SIGTERM, (f as *const std::ffi::c_void) as usize);
|
||||||
|
let _ = libc::signal(libc::SIGQUIT, (f as *const std::ffi::c_void) as usize);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return an Error Result object from error string
|
||||||
|
///
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! ERR {
|
||||||
|
($x:expr) => {
|
||||||
|
std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
format!("({}:{}): {}", file!(), line!(), $x),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/// Bit value at address
|
||||||
|
///
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! BITV {
|
||||||
|
($v:expr,$i:expr) => {
|
||||||
|
($v & (1 << $i)) >> $i
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user