Create start subcommand implementation for unix systems

This commit is contained in:
Federico Terzi 2019-09-14 10:03:25 +02:00
parent 4a2b0b9881
commit d2b812b275
3 changed files with 69 additions and 15 deletions

1
Cargo.lock generated
View File

@ -229,6 +229,7 @@ dependencies = [
"cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -17,6 +17,10 @@ simplelog = "0.7.1"
zip = "0.5.3" zip = "0.5.3"
fs2 = "0.4.3" fs2 = "0.4.3"
[target.'cfg(unix)'.dependencies]
libc = "0.2.62"
[dev-dependencies] [dev-dependencies]
tempfile = "3.1.0" tempfile = "3.1.0"

View File

@ -1,22 +1,24 @@
use std::sync::{mpsc}; use std::thread;
use crate::matcher::scrolling::ScrollingMatcher; use std::fs::{File, OpenOptions};
use crate::engine::Engine; use std::path::Path;
use std::process::exit;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use std::time::Duration;
use clap::{App, Arg, SubCommand};
use fs2::FileExt;
use log::{error, info, LevelFilter};
use simplelog::{CombinedLogger, SharedLogger, TerminalMode, TermLogger};
use crate::config::ConfigSet; use crate::config::ConfigSet;
use crate::config::runtime::RuntimeConfigManager; use crate::config::runtime::RuntimeConfigManager;
use crate::engine::Engine;
use crate::event::*;
use crate::event::manager::{DefaultEventManager, EventManager};
use crate::matcher::scrolling::ScrollingMatcher;
use crate::system::SystemManager; use crate::system::SystemManager;
use crate::ui::UIManager; use crate::ui::UIManager;
use crate::event::*;
use crate::event::manager::{EventManager, DefaultEventManager};
use std::{thread};
use clap::{App, Arg, SubCommand};
use std::path::Path;
use std::sync::mpsc::Receiver;
use log::{info, error, LevelFilter};
use simplelog::{CombinedLogger, TermLogger, TerminalMode, SharedLogger};
use std::process::exit;
use std::time::Duration;
use std::fs::{File, OpenOptions};
use fs2::FileExt;
mod ui; mod ui;
mod event; mod event;
@ -52,6 +54,8 @@ fn main() {
.about("Tool to detect current window properties, to simplify filters creation.")) .about("Tool to detect current window properties, to simplify filters creation."))
.subcommand(SubCommand::with_name("daemon") .subcommand(SubCommand::with_name("daemon")
.about("Start the daemon without spawning a new process.")) .about("Start the daemon without spawning a new process."))
.subcommand(SubCommand::with_name("start")
.about("Start the daemon spawning a new process in the background."))
.subcommand(SubCommand::with_name("status") .subcommand(SubCommand::with_name("status")
.about("Check if the espanso daemon is running or not.")) .about("Check if the espanso daemon is running or not."))
.get_matches(); .get_matches();
@ -107,12 +111,18 @@ fn main() {
return; return;
} }
if let Some(matches) = matches.subcommand_matches("start") {
start_main(config_set);
return;
}
if let Some(matches) = matches.subcommand_matches("status") { if let Some(matches) = matches.subcommand_matches("status") {
status_main(); status_main();
return; return;
} }
} }
/// Daemon subcommand, start the event loop and spawn a background thread worker
fn daemon_main(config_set: ConfigSet) { fn daemon_main(config_set: ConfigSet) {
// Try to acquire lock file // Try to acquire lock file
let lock_file = acquire_lock(); let lock_file = acquire_lock();
@ -134,6 +144,7 @@ fn daemon_main(config_set: ConfigSet) {
context.eventloop(); context.eventloop();
} }
/// Background thread worker for the daemon
fn daemon_background(receive_channel: Receiver<Event>, config_set: ConfigSet) { fn daemon_background(receive_channel: Receiver<Event>, config_set: ConfigSet) {
let system_manager = system::get_manager(); let system_manager = system::get_manager();
let config_manager = RuntimeConfigManager::new(config_set, system_manager); let config_manager = RuntimeConfigManager::new(config_set, system_manager);
@ -164,6 +175,44 @@ fn daemon_background(receive_channel: Receiver<Event>, config_set: ConfigSet) {
event_manager.eventloop(); event_manager.eventloop();
} }
/// start subcommand, spawn a background espanso process.
fn start_main(config_set: ConfigSet) {
// Try to acquire lock file
let lock_file = acquire_lock();
if lock_file.is_none() {
println!("espanso is already running.");
exit(3);
}
release_lock(lock_file.unwrap());
if cfg!(target_os = "windows") {
// TODO: start windows detached
}else{
unsafe {
let pid = libc::fork();
if pid < 0 {
error!("Unable to fork.");
exit(4);
}
if pid > 0 { // Parent process exit
println!("Daemon started!");
exit(0);
}
// Spawned process
// Create a new SID for the child process
let sid = libc::setsid();
if sid < 0 {
exit(5);
}
}
daemon_main(config_set);
}
}
/// status subcommand, print the current espanso status
fn status_main() { fn status_main() {
let lock_file = acquire_lock(); let lock_file = acquire_lock();
if let Some(lock_file) = lock_file { if let Some(lock_file) = lock_file {