roezio: startup WIP

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2022-08-30 15:31:59 +02:00
parent 1575e7c8aa
commit aca6983bef
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2
3 changed files with 133 additions and 1 deletions

View file

@ -10,7 +10,7 @@ authors = [
description = "A console XMPP client"
[dependencies]
pyo3 = { version = "0.17", features = ["extension-module"] }
pyo3 = { version = "0.17", features = ["auto-initialize", "nightly"] }
nom = "7.1"
chrono = "0.4"
ncurses = "5"
@ -20,6 +20,9 @@ clap = { version = "3.2.17", features = ["derive"] }
directories = "4.0.1"
configparser = "3.0.1"
jid = "0.9.4"
libc = "0.2.132"
log = "0.4.17"
simplelog = "0.12.0"
[lib]
crate-type = ["cdylib"]

View file

@ -21,10 +21,14 @@ use std::io;
use std::num::TryFromIntError;
use std::path::PathBuf;
use pyo3::PyErr;
#[derive(Debug)]
pub(crate) enum Error {
IOError(io::Error),
IntError(TryFromIntError),
PyError(PyErr),
StartupCheck(String),
UnableToCreateConfigDir,
InvalidConfigValueType(ConfigValue),
InvalidValueType(String),
@ -36,6 +40,8 @@ impl fmt::Display for Error {
match self {
Error::IOError(e) => write!(f, "io error: {}", e),
Error::IntError(e) => write!(f, "int error: {}", e),
Error::PyError(e) => write!(f, "python error: {}", e),
Error::StartupCheck(e) => write!(f, "Startup check error: {}", e),
Error::UnableToCreateConfigDir => write!(f, "Unable to create config dir"),
Error::InvalidConfigValueType(err) => write!(f, "Invalid ConfigValue type: {}", err),
Error::InvalidValueType(err) => write!(f, "Invalid value type: {}", err),
@ -59,3 +65,9 @@ impl From<TryFromIntError> for Error {
Error::IntError(err)
}
}
impl From<PyErr> for Error {
fn from(err: PyErr) -> Error {
Error::PyError(err)
}
}

117
src/main.rs Normal file
View file

@ -0,0 +1,117 @@
// Copyright (C) 2018-2099 The crate authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#![feature(once_cell)]
mod args;
mod config;
mod error;
mod xdg;
use crate::args::Args;
use crate::config::Config;
use crate::error::Error;
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use clap::Parser;
use libc;
use log;
use simplelog::WriteLogger;
use pyo3::{Python, PyResult, py_run};
fn main() -> Result<(), Error> {
if unsafe { libc::getuid() == 0 } {
return Err(Error::StartupCheck(String::from("Do not run as root")));
}
io::stdout().write_all(b"\x1b]0;poezio\x07")?;
io::stdout().flush()?;
let args = Args::parse();
let firstrun = !args.filename.exists();
if firstrun {
let parent = args
.filename
.parent()
.ok_or(Error::UnableToCreateConfigDir)?;
fs::create_dir_all(parent).map_err(|_| Error::UnableToCreateConfigDir)?;
let default = include_bytes!("../data/default_config.cfg");
let mut file = fs::File::create::<&Path>(args.filename.as_ref())?;
file.write_all(default)?;
};
let config: Config = Config::builder::<&Path>(args.filename.as_ref()).build()?;
// println!("Config: {:?}", config);
config.setup_logging(None::<PathBuf>)?;
if args.check_config {
config.check_config();
return Ok(())
}
let custom_version = args.custom_version;
update_themes_dir()?;
Python::with_gil(|py| -> PyResult<()> {
let pathlib = py.import("pathlib")?;
let path = pathlib.getattr("Path")?;
let configfile = path.call1((args.filename.clone(),))?;
py_run!(py, configfile firstrun custom_version, r#"
import signal
from poezio import config
from poezio.core.core import Core
config.config = config.Config(configfile) # XXX: doesn't work.
signal.signal(signal.SIGINT, signal.SIG_IGN)
cocore = Core(custom_version, firstrun)
signal.signal(signal.SIGUSR1, cocore.sigusr_handler) # reload the config
signal.signal(signal.SIGHUP, cocore.exit_from_signal)
signal.signal(signal.SIGTERM, cocore.exit_from_signal)
cocore.start()
from slixmpp.exceptions import IqError, IqTimeout
# Warning: asyncio must always be imported after the config. Otherwise
# the asyncio logger will not follow our configuration and won't write
# the tracebacks in the correct file, etc
import asyncio
loop = asyncio.get_event_loop()
loop.set_exception_handler(cocore.loop_exception_handler)
loop.add_reader(sys.stdin, cocore.on_input_readable)
loop.add_signal_handler(signal.SIGWINCH, cocore.sigwinch_handler)
cocore.xmpp.start()
loop.run_forever()
# We reach this point only when loop.stop() is called
try:
cocore.reset_curses()
except:
pass
"#);
Ok(())
})?;
Ok(())
}