aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoee Shapira <35409124+5c077m4n@users.noreply.github.com>2020-11-19 12:15:59 +0200
committerGitHub <noreply@github.com>2020-11-19 11:15:59 +0100
commit5ddf95a16c8d1c9632ba6cef56f55fcf8bf9e4ea (patch)
tree94a00125fb99f7cf0953e20052eb000647c9f212
parentfix(ux): disable move focus when in full screen (#49) (diff)
downloadsl0ppij-5ddf95a16c8d1c9632ba6cef56f55fcf8bf9e4ea.tar.gz
sl0ppij-5ddf95a16c8d1c9632ba6cef56f55fcf8bf9e4ea.tar.xz
sl0ppij-5ddf95a16c8d1c9632ba6cef56f55fcf8bf9e4ea.zip
fix(compatibility): some fixes for htop (#53)
* Moved all log to file functions to one module. * Moved logging to file function to utils module. * Housekeeping. * Housekeeping. * Started investigation into htop CSIs. * Used better function for scrolling. * Minor cleanup. * Cleanup and start of scroll region rotation. * Implemented scroll region rotation. * Improved performace. * New SCI found. * Typo. * Typo. * Removed logging function. * Added scroll rotation functions. * Typo. * Moved all logging function to one module. * Attempt at making htop work. * Reverted unneeded changes. * Improved log file name creation. * Ran rust fmt. * PR review edits. * PR review edits. * Used mark_for_rerender function. * Removed _ prefix from logging functions.
-rw-r--r--src/boundaries.rs12
-rw-r--r--src/layout.rs12
-rw-r--r--src/main.rs38
-rw-r--r--src/os_input_output.rs12
-rw-r--r--src/pty_bus.rs35
-rw-r--r--src/screen.rs18
-rw-r--r--src/terminal_pane/scroll.rs58
-rw-r--r--src/terminal_pane/terminal_pane.rs101
-rw-r--r--src/utils/consts.rs3
-rw-r--r--src/utils/logging.rs58
-rw-r--r--src/utils/mod.rs2
11 files changed, 188 insertions, 161 deletions
diff --git a/src/boundaries.rs b/src/boundaries.rs
index 436d767b..9f414f1c 100644
--- a/src/boundaries.rs
+++ b/src/boundaries.rs
@@ -1,17 +1,5 @@
use std::collections::HashMap;
-fn _debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
pub mod boundary_type {
pub const TOP_RIGHT: &str = "┐";
pub const VERTICAL: &str = "│";
diff --git a/src/layout.rs b/src/layout.rs
index e80c76b2..f4297bfd 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -1,18 +1,6 @@
use crate::terminal_pane::PositionAndSize;
use serde::{Deserialize, Serialize};
-fn _debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
fn split_space_to_parts_vertically(
space_to_split: &PositionAndSize,
percentages: Vec<u8>,
diff --git a/src/main.rs b/src/main.rs
index 315e8eb1..d331451c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,12 @@
-#[cfg(test)]
-mod tests;
-
mod boundaries;
mod layout;
mod os_input_output;
mod pty_bus;
mod screen;
mod terminal_pane;
+#[cfg(test)]
+mod tests;
+mod utils;
use std::io::{Read, Write};
use std::os::unix::net::UnixStream;
@@ -22,6 +22,7 @@ use crate::layout::Layout;
use crate::os_input_output::{get_os_input, OsApi};
use crate::pty_bus::{PtyBus, PtyInstruction, VteEvent};
use crate::screen::{Screen, ScreenInstruction};
+use crate::utils::{consts::MOSAIC_TMP_FOLDER, logging::*};
#[derive(Serialize, Deserialize, Debug)]
enum ApiCommand {
@@ -53,46 +54,28 @@ pub struct Opt {
debug: bool,
}
-fn _debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
-fn delete_log_files() -> std::io::Result<()> {
- std::fs::remove_dir_all("/tmp/mosaic-logs").ok();
- std::fs::create_dir_all("/tmp/mosaic-logs").ok();
- Ok(())
-}
-
pub fn main() {
let opts = Opt::from_args();
if opts.split.is_some() {
match opts.split {
Some('h') => {
- let mut stream = UnixStream::connect("/tmp/mosaic").unwrap();
+ let mut stream = UnixStream::connect(MOSAIC_TMP_FOLDER).unwrap();
let api_command = bincode::serialize(&ApiCommand::SplitHorizontally).unwrap();
stream.write_all(&api_command).unwrap();
}
Some('v') => {
- let mut stream = UnixStream::connect("/tmp/mosaic").unwrap();
+ let mut stream = UnixStream::connect(MOSAIC_TMP_FOLDER).unwrap();
let api_command = bincode::serialize(&ApiCommand::SplitVertically).unwrap();
stream.write_all(&api_command).unwrap();
}
_ => {}
};
} else if opts.move_focus {
- let mut stream = UnixStream::connect("/tmp/mosaic").unwrap();
+ let mut stream = UnixStream::connect(MOSAIC_TMP_FOLDER).unwrap();
let api_command = bincode::serialize(&ApiCommand::MoveFocus).unwrap();
stream.write_all(&api_command).unwrap();
} else if opts.open_file.is_some() {
- let mut stream = UnixStream::connect("/tmp/mosaic").unwrap();
+ let mut stream = UnixStream::connect(MOSAIC_TMP_FOLDER).unwrap();
let file_to_open = opts.open_file.unwrap();
let api_command = bincode::serialize(&ApiCommand::OpenFile(file_to_open)).unwrap();
stream.write_all(&api_command).unwrap();
@@ -109,7 +92,8 @@ pub enum AppInstruction {
pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
let mut active_threads = vec![];
- delete_log_files().unwrap();
+ delete_log_dir().unwrap();
+ delete_log_file().unwrap();
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
os_input.into_raw_mode(0);
@@ -335,7 +319,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
let mut buffer = [0; 10]; // TODO: more accurately
stdin.read(&mut buffer).expect("failed to read stdin");
// uncomment this to print the entered character to a log file (/tmp/mosaic-log.txt) for debugging
- // _debug_log_to_file(format!("buffer {:?}", buffer));
+ //crate::utils::logging::debug_log_to_file(format!("buffer {:?}", buffer));
match buffer {
[10, 0, 0, 0, 0, 0, 0, 0, 0, 0] => {
// ctrl-j
diff --git a/src/os_input_output.rs b/src/os_input_output.rs
index 251b8c5e..ecd18edc 100644
--- a/src/os_input_output.rs
+++ b/src/os_input_output.rs
@@ -58,18 +58,6 @@ pub fn set_terminal_size_using_fd(fd: RawFd, columns: u16, rows: u16) {
unsafe { ioctl(fd, TIOCSWINSZ.into(), &winsize) };
}
-fn _debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
fn handle_command_exit(mut child: Child) {
let signals = ::signal_hook::iterator::Signals::new(&[::signal_hook::SIGINT]).unwrap();
'handle_exit: loop {
diff --git a/src/pty_bus.rs b/src/pty_bus.rs
index fed8f7f7..49334736 100644
--- a/src/pty_bus.rs
+++ b/src/pty_bus.rs
@@ -11,6 +11,7 @@ use std::path::PathBuf;
use crate::layout::Layout;
use crate::os_input_output::OsApi;
+use crate::utils::logging::debug_to_file;
use crate::ScreenInstruction;
pub struct ReadFromPid {
@@ -27,38 +28,6 @@ impl ReadFromPid {
}
}
-fn _debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
-fn debug_to_file(message: u8, pid: RawFd) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut path = PathBuf::new();
- path.push(
- [
- String::from("/tmp/mosaic-logs/mosaic-"),
- pid.to_string(),
- String::from(".log"),
- ]
- .concat(),
- );
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open(path)
- .unwrap();
- file.write_all(&[message]).unwrap();
-}
-
impl Stream for ReadFromPid {
type Item = Vec<u8>;
fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
@@ -208,7 +177,7 @@ fn stream_terminal_bytes(
let bytes_is_empty = bytes.is_empty();
for byte in bytes {
if debug {
- debug_to_file(byte, pid);
+ debug_to_file(byte, pid).unwrap();
}
vte_parser.advance(&mut vte_event_sender, byte);
}
diff --git a/src/screen.rs b/src/screen.rs
index cf67909c..76c7b182 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -19,19 +19,7 @@ use crate::AppInstruction;
*
*/
-fn _debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
-const CURSOR_HEIGHT_WIDGH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this
+const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this
type BorderAndPaneIds = (usize, Vec<RawFd>);
@@ -206,7 +194,7 @@ impl Screen {
(0, 0),
|(current_longest_edge, current_terminal_id_to_split), id_and_terminal_to_check| {
let (id_of_terminal_to_check, terminal_to_check) = id_and_terminal_to_check;
- let terminal_size = (terminal_to_check.get_rows() * CURSOR_HEIGHT_WIDGH_RATIO)
+ let terminal_size = (terminal_to_check.get_rows() * CURSOR_HEIGHT_WIDTH_RATIO)
* terminal_to_check.get_columns();
if terminal_size > current_longest_edge {
(terminal_size, *id_of_terminal_to_check)
@@ -222,7 +210,7 @@ impl Screen {
ws_xpixel: terminal_to_split.get_x() as u16,
ws_ypixel: terminal_to_split.get_y() as u16,
};
- if terminal_to_split.get_rows() * CURSOR_HEIGHT_WIDGH_RATIO
+ if terminal_to_split.get_rows() * CURSOR_HEIGHT_WIDTH_RATIO
> terminal_to_split.get_columns()
{
let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws);
diff --git a/src/terminal_pane/scroll.rs b/src/terminal_pane/scroll.rs
index 3ced3828..5884ea32 100644
--- a/src/terminal_pane/scroll.rs
+++ b/src/terminal_pane/scroll.rs
@@ -26,18 +26,6 @@ pub struct CanonicalLine {
pub wrapped_fragments: Vec<WrappedFragment>,
}
-fn debug_log_to_file(message: String) {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
-}
-
impl CanonicalLine {
pub fn new() -> Self {
CanonicalLine {
@@ -163,6 +151,9 @@ impl CursorPosition {
pub fn move_to_next_canonical_line(&mut self) {
self.line_index.0 += 1;
}
+ pub fn move_to_prev_canonical_line(&mut self) {
+ self.line_index.0 -= 1;
+ }
pub fn move_to_beginning_of_linewrap(&mut self) {
self.column_index = 0;
}
@@ -307,8 +298,7 @@ impl Scroll {
}
}
if current_canonical_line_index == self.canonical_lines.len() - 1 {
- let new_canonical_line = CanonicalLine::new();
- self.canonical_lines.push(new_canonical_line);
+ self.canonical_lines.push(CanonicalLine::new());
self.cursor_position.move_to_next_canonical_line();
self.cursor_position.move_to_beginning_of_canonical_line();
} else if current_canonical_line_index < self.canonical_lines.len() - 1 {
@@ -517,6 +507,46 @@ impl Scroll {
}
}
}
+ /// [scroll_up](https://github.com/alacritty/alacritty/blob/ec42b42ce601808070462111c0c28edb0e89babb/alacritty_terminal/src/grid/mod.rs#L261)
+ /// This function takes the first line of the scroll region and moves it to the bottom (count times)
+ pub fn rotate_scroll_region_up(&mut self, count: usize) {
+ if let Some((_, scroll_region_bottom)) = self.scroll_region {
+ if self.show_cursor {
+ let scroll_region_bottom_index = scroll_region_bottom - 1;
+ self.cursor_position
+ .move_to_canonical_line(scroll_region_bottom_index);
+
+ let new_empty_lines = vec![CanonicalLine::new(); count];
+ self.canonical_lines.splice(
+ scroll_region_bottom_index..scroll_region_bottom_index + 1,
+ new_empty_lines,
+ );
+
+ self.cursor_position
+ .move_to_canonical_line(scroll_region_bottom_index + count);
+ }
+ }
+ }
+ /// [scroll_down](https://github.com/alacritty/alacritty/blob/ec42b42ce601808070462111c0c28edb0e89babb/alacritty_terminal/src/grid/mod.rs#L221)
+ /// This function takes the last line of the scroll region and moves it to the top (count times)
+ pub fn rotate_scroll_region_down(&mut self, count: usize) {
+ if let Some((scroll_region_top, _)) = self.scroll_region {
+ if self.show_cursor {
+ let scroll_region_top_index = scroll_region_top - 1;
+ self.cursor_position
+ .move_to_canonical_line(scroll_region_top_index);
+
+ let new_empty_lines = vec![CanonicalLine::new(); count];
+ self.canonical_lines.splice(
+ scroll_region_top_index..scroll_region_top_index,
+ new_empty_lines,
+ );
+
+ self.cursor_position
+ .move_to_canonical_line(scroll_region_top_index + count);
+ }
+ }
+ }
pub fn move_viewport_up(&mut self, count: usize) {
if let Some(current_offset) = self.viewport_bottom_offset.as_mut() {
*current_offset += count;
diff --git a/src/terminal_pane/terminal_pane.rs b/src/terminal_pane/terminal_pane.rs
index fc1cc207..bdaf6417 100644
--- a/src/terminal_pane/terminal_pane.rs
+++ b/src/terminal_pane/terminal_pane.rs
@@ -7,6 +7,7 @@ use crate::terminal_pane::terminal_character::{
AnsiCode, CharacterStyles, NamedColor, TerminalCharacter,
};
use crate::terminal_pane::Scroll;
+use crate::utils::logging::{debug_log_to_file, debug_log_to_file_pid_0};
use crate::VteEvent;
#[derive(Clone, Copy, Debug)]
@@ -61,11 +62,14 @@ impl TerminalPane {
position_and_size_override: None,
}
}
+ pub fn mark_for_rerender(&mut self) {
+ self.should_render = true;
+ }
pub fn handle_event(&mut self, event: VteEvent) {
match event {
VteEvent::Print(c) => {
self.print(c);
- self.should_render = true;
+ self.mark_for_rerender();
}
VteEvent::Execute(byte) => {
self.execute(byte);
@@ -95,57 +99,57 @@ impl TerminalPane {
self.position_and_size.x += count;
self.position_and_size.columns -= count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn reduce_width_left(&mut self, count: usize) {
self.position_and_size.columns -= count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn increase_width_left(&mut self, count: usize) {
self.position_and_size.x -= count;
self.position_and_size.columns += count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn increase_width_right(&mut self, count: usize) {
self.position_and_size.columns += count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn reduce_height_down(&mut self, count: usize) {
self.position_and_size.y += count;
self.position_and_size.rows -= count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn increase_height_down(&mut self, count: usize) {
self.position_and_size.rows += count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn increase_height_up(&mut self, count: usize) {
self.position_and_size.y -= count;
self.position_and_size.rows += count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn reduce_height_up(&mut self, count: usize) {
self.position_and_size.rows -= count;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn change_size_p(&mut self, position_and_size: &PositionAndSize) {
self.position_and_size = *position_and_size;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
// TODO: merge these two methods
pub fn change_size(&mut self, ws: &Winsize) {
self.position_and_size.columns = ws.ws_col as usize;
self.position_and_size.rows = ws.ws_row as usize;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn get_x(&self) -> usize {
match self.position_and_size_override {
@@ -210,7 +214,7 @@ impl TerminalPane {
}
character_styles.clear();
}
- self.should_render = false;
+ self.mark_for_rerender();
Some(vte_output)
} else {
None
@@ -225,15 +229,23 @@ impl TerminalPane {
}
pub fn scroll_up(&mut self, count: usize) {
self.scroll.move_viewport_up(count);
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn scroll_down(&mut self, count: usize) {
self.scroll.move_viewport_down(count);
- self.should_render = true;
+ self.mark_for_rerender();
+ }
+ pub fn rotate_scroll_region_up(&mut self, count: usize) {
+ self.scroll.rotate_scroll_region_up(count);
+ self.mark_for_rerender();
+ }
+ pub fn rotate_scroll_region_down(&mut self, count: usize) {
+ self.scroll.rotate_scroll_region_down(count);
+ self.mark_for_rerender();
}
pub fn clear_scroll(&mut self) {
self.scroll.reset_viewport();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn override_size_and_position(&mut self, x: usize, y: usize, size: &Winsize) {
let position_and_size_override = PositionAndSize {
@@ -244,17 +256,17 @@ impl TerminalPane {
};
self.position_and_size_override = Some(position_and_size_override);
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
pub fn reset_size_and_position_override(&mut self) {
self.position_and_size_override = None;
self.reflow_lines();
- self.should_render = true;
+ self.mark_for_rerender();
}
fn add_newline(&mut self) {
self.scroll.add_canonical_line();
// self.reset_all_ansi_codes(); // TODO: find out if we should be resetting here or not
- self.should_render = true;
+ self.mark_for_rerender();
}
fn move_to_beginning_of_line(&mut self) {
self.scroll.move_cursor_to_beginning_of_linewrap();
@@ -267,20 +279,6 @@ impl TerminalPane {
}
}
-fn debug_log_to_file(message: String, pid: RawFd) {
- if pid == 3 {
- use std::fs::OpenOptions;
- use std::io::prelude::*;
- let mut file = OpenOptions::new()
- .append(true)
- .create(true)
- .open("/tmp/mosaic-log.txt")
- .unwrap();
- file.write_all(message.as_bytes()).unwrap();
- file.write_all("\n".as_bytes()).unwrap();
- }
-}
-
impl vte::Perform for TerminalPane {
fn print(&mut self, c: char) {
// apparently, building TerminalCharacter like this without a "new" method
@@ -632,7 +630,8 @@ impl vte::Perform for TerminalPane {
.pending_styles
.background(Some(AnsiCode::NamedColor(NamedColor::White)));
} else {
- debug_log_to_file(format!("unhandled csi m code {:?}", params), self.pid);
+ debug_log_to_file_pid_0(format!("unhandled csi m code {:?}", params), self.pid)
+ .unwrap();
}
} else if c == 'C' {
// move cursor forward
@@ -685,7 +684,7 @@ impl vte::Perform for TerminalPane {
match params.get(0) {
Some(25) => {
self.scroll.hide_cursor();
- self.should_render = true;
+ self.mark_for_rerender();
}
_ => {}
};
@@ -700,7 +699,7 @@ impl vte::Perform for TerminalPane {
match params.get(0) {
Some(25) => {
self.scroll.show_cursor();
- self.should_render = true;
+ self.mark_for_rerender();
}
_ => {}
};
@@ -741,8 +740,38 @@ impl vte::Perform for TerminalPane {
.add_empty_lines_in_scroll_region(line_count_to_add);
} else if c == 'q' || c == 'd' || c == 'X' || c == 'G' {
// ignore for now to run on mac
+ } else if c == 'T' {
+ /*
+ * 124 54 T SD
+ * Scroll down, new lines inserted at top of screen
+ * [4T = Scroll down 4, bring previous lines back into view
+ */
+ debug_log_to_file(format!(
+ "htop (only?) linux csi: {}->{:?} ({:?} - ignore: {})",
+ c, params, _intermediates, _ignore
+ ))
+ .unwrap();
+ let line_count: i64 = *params.get(0).expect("A number of lines was expected.");
+
+ if line_count >= 0 {
+ self.rotate_scroll_region_up(line_count as usize);
+ } else {
+ self.rotate_scroll_region_down(line_count.abs() as usize);
+ }
+ } else if c == 'P' {
+ /*
+ * 120 50 P * DCH
+ * Delete Character, from current position to end of field
+ * [4P = Delete 4 characters, VT102 series
+ */
+ debug_log_to_file(format!(
+ "htop (only?) linux csi: {}->{:?} (intermediates: {:?}, ignore: {})",
+ c, params, _intermediates, _ignore
+ ))
+ .unwrap();
} else {
- panic!("unhandled csi: {:?}->{:?}", c, params);
+ debug_log_to_file(format!("Unhandled csi: {}->{:?}", c, params)).unwrap();
+ panic!("unhandled csi: {}->{:?}", c, params);
}
}
diff --git a/src/utils/consts.rs b/src/utils/consts.rs
new file mode 100644
index 00000000..5eb96c67
--- /dev/null
+++ b/src/utils/consts.rs
@@ -0,0 +1,3 @@
+pub const MOSAIC_TMP_LOG_FILE: &str = "/tmp/mosaic-log.txt";
+pub const MOSAIC_TMP_LOG_DIR: &str = "/tmp/mosaic-log";
+pub const MOSAIC_TMP_FOLDER: &str = "/tmp/mosaic";
diff --git a/src/utils/logging.rs b/src/utils/logging.rs
new file mode 100644
index 00000000..77e924a9
--- /dev/null
+++ b/src/utils/logging.rs
@@ -0,0 +1,58 @@
+use std::{
+ fs,
+ io::{self, prelude::*},
+ os::unix::io::RawFd,
+ path::PathBuf,
+};
+
+use crate::utils::consts::{MOSAIC_TMP_LOG_DIR, MOSAIC_TMP_LOG_FILE};
+
+pub fn debug_log_to_file(message: String) -> io::Result<()> {
+ let mut file = fs::OpenOptions::new()
+ .append(true)
+ .create(true)
+ .open(MOSAIC_TMP_LOG_FILE)?;
+ file.write_all(message.as_bytes())?;
+ file.write_all("\n".as_bytes())?;
+
+ Ok(())
+}
+
+pub fn debug_log_to_file_pid_0(message: String, pid: RawFd) -> io::Result<()> {
+ if pid == 0 {
+ debug_log_to_file(message)?;
+ }
+
+ Ok(())
+}
+
+pub fn delete_log_file() -> io::Result<()> {
+ if fs::metadata(MOSAIC_TMP_LOG_FILE).is_ok() {
+ fs::remove_file(MOSAIC_TMP_LOG_FILE)?;
+ }
+
+ Ok(())
+}
+
+pub fn delete_log_dir() -> io::Result<()> {
+ if fs::metadata(MOSAIC_TMP_LOG_DIR).is_ok() {
+ fs::remove_dir_all(MOSAIC_TMP_LOG_DIR)?;
+ }
+ fs::create_dir_all(MOSAIC_TMP_LOG_DIR)?;
+
+ Ok(())
+}
+
+pub fn debug_to_file(message: u8, pid: RawFd) -> io::Result<()> {
+ let mut path = PathBuf::new();
+ path.push(MOSAIC_TMP_LOG_DIR);
+ path.push(format!("mosaic-{}.log", pid.to_string()));
+
+ let mut file = fs::OpenOptions::new()
+ .append(true)
+ .create(true)
+ .open(path)?;
+ file.write_all(&[message])?;
+
+ Ok(())
+}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
new file mode 100644
index 00000000..140eec18
--- /dev/null
+++ b/src/utils/mod.rs
@@ -0,0 +1,2 @@
+pub mod consts;
+pub mod logging;