├── libcommon ├── README.md ├── src │ ├── lib.rs │ ├── util.rs │ ├── error.rs │ └── ipc.rs └── Cargo.toml ├── libgreeter ├── README.md ├── Cargo.toml └── src │ └── lib.rs ├── theme ├── background.png └── rdm.theme ├── scripts ├── launch_xephyr.sh ├── launch_vm.sh └── dbus_test.sh ├── rdm ├── src │ ├── session.rs │ ├── constants.rs │ ├── bus.rs │ ├── ipc.rs │ ├── manager.rs │ ├── main.rs │ └── server.rs └── Cargo.toml ├── data ├── rdm.pam ├── rdm.service ├── rdm.dbus └── login1.xml ├── docs ├── main.md ├── questions.md ├── other_dms.md └── architecture.md ├── .gitignore ├── Cargo.toml ├── .travis.yml ├── rdm-greeter ├── Cargo.toml └── src │ ├── constants.rs │ ├── main.rs │ └── ui.rs ├── Makefile ├── LICENSE ├── README.md └── Cargo.lock /libcommon/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libgreeter/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /theme/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1wilkens/rdm/HEAD/theme/background.png -------------------------------------------------------------------------------- /scripts/launch_xephyr.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | Xephyr -br -ac -noreset -screen 1280x1280 -dpi 192 :1 4 | -------------------------------------------------------------------------------- /libcommon/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | #[macro_use] 4 | extern crate slog; 5 | 6 | pub mod error; 7 | pub mod ipc; 8 | pub mod util; 9 | -------------------------------------------------------------------------------- /rdm/src/session.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub struct Session { 3 | } 4 | 5 | impl Session { 6 | pub fn new() -> Session { 7 | Session {} 8 | } 9 | } -------------------------------------------------------------------------------- /data/rdm.pam: -------------------------------------------------------------------------------- 1 | #%PAM-1.0 2 | 3 | auth include system-login 4 | account include system-login 5 | password include system-login 6 | session include system-login 7 | -------------------------------------------------------------------------------- /scripts/launch_vm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | qemu-system-x86_64 -cdrom archlinux.iso -boot order=d -drive file=disk.raw,format=raw -enable-kvm -m 2G -net nic -net user,smb=/home/florian/src 4 | -------------------------------------------------------------------------------- /docs/main.md: -------------------------------------------------------------------------------- 1 | # 2 | 3 | ## Intro 4 | 5 | ## Goals 6 | 7 | ## Constraints 8 | 9 | - Client/Server process architecture as the session process must not be reused (ref) 10 | - 11 | -------------------------------------------------------------------------------- /scripts/dbus_test.sh: -------------------------------------------------------------------------------- 1 | sudo dbus-send --system --print-reply \ 2 | --dest=com.github.mrfloya.RDM \ 3 | /com/github/mrfloya/RDM \ 4 | com.github.mrfloya.RDM.Hello 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | 10 | # Generated by Cargo 11 | **/target/ 12 | 13 | # Ignore tmp files 14 | *~ 15 | 16 | # Ignore debug results (*.log, *.txt) 17 | *.log 18 | *.txt 19 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "libcommon", 4 | "libgreeter", 5 | "rdm", 6 | "rdm-greeter" 7 | ] 8 | 9 | [profile.release] 10 | lto = true 11 | 12 | [replace] 13 | #"rdmgreeter:0.0.1" = { path = "./libgreeter" } 14 | #"rdmcommon:0.0.1" = { path = "./libcommon" } -------------------------------------------------------------------------------- /libcommon/src/util.rs: -------------------------------------------------------------------------------- 1 | use slog::{Drain, Logger}; 2 | use slog_term::{FullFormat, PlainSyncDecorator}; 3 | 4 | pub fn plain_logger() -> Logger { 5 | let decorator = PlainSyncDecorator::new(::std::io::stdout()); 6 | let drain = FullFormat::new(decorator).build().fuse(); 7 | 8 | Logger::root(drain, o!()) 9 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | cache: cargo 3 | rust: 4 | - nightly 5 | 6 | dist: trusty 7 | sudo: false 8 | 9 | addons: 10 | apt: 11 | packages: 12 | - libpam0g-dev 13 | - libgtk-3-dev 14 | - libdbus-1-dev 15 | 16 | script: 17 | - cargo build 18 | - cargo test 19 | 20 | notifications: 21 | email: 22 | on_success: never 23 | -------------------------------------------------------------------------------- /data/rdm.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Rust Display Manager 3 | Conflicts=getty@tty1.service 4 | After=systemd-user-sessions.service getty@tty1.service plymouth-quit.service 5 | 6 | [Service] 7 | #Environment="G_MESSAGES_DEBUG=all" 8 | #Environment="GTK_DEBUG=all" 9 | #Restart=always 10 | PrivateTmp=yes 11 | RuntimeDirectory=rdm 12 | RuntimeDirectoryMode=0755 13 | ExecStart=/usr/local/bin/rdm 14 | 15 | [Install] 16 | Alias=display-manager.service 17 | -------------------------------------------------------------------------------- /libcommon/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rdmcommon" 3 | version = "0.0.1" 4 | authors = ["Florian Wilkens "] 5 | description = "Common library for rdm" 6 | repository = "https://github.com/1wilkens/rdm" 7 | readme = "README.md" 8 | license = "MIT" 9 | 10 | edition = "2018" 11 | 12 | [dependencies] 13 | slog = "2.4.1" 14 | slog-term = "2.4.0" 15 | 16 | bytes = "^1.0" 17 | #byteorder = "1.1.0" 18 | tokio = "^1.5" 19 | tokio-util = { version = "^0.7", features = ["codec"]} 20 | -------------------------------------------------------------------------------- /libgreeter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rdmgreeter" 3 | version = "0.0.1" 4 | authors = ["Florian Wilkens "] 5 | description = "Greeter library for rdm" 6 | repository = "https://github.com/1wilkens/rdm" 7 | readme = "README.md" 8 | license = "MIT" 9 | 10 | edition = "2018" 11 | 12 | [dependencies] 13 | slog = "2.0" 14 | 15 | futures = "^0.3" 16 | tokio = { version = "^1.15" } 17 | tokio-util = { version = "^0.7", features = ["codec"]} 18 | 19 | rdmcommon = { path = "../libcommon"} 20 | -------------------------------------------------------------------------------- /rdm-greeter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rdm-greeter" 3 | version = "0.0.1" 4 | authors = ["Florian Wilkens "] 5 | description = "Default greeter for rdm" 6 | repository = "https://github.com/1wilkens/rdm" 7 | readme = "README.md" 8 | license = "MIT" 9 | 10 | edition = "2018" 11 | 12 | [dependencies] 13 | slog = "2.0" 14 | slog-async = "2.0" 15 | slog-term = "2.0" 16 | 17 | tokio = { version = "^1.15" } 18 | 19 | rdmcommon = { path = "../libcommon" } 20 | rdmgreeter = { path = "../libgreeter" } 21 | 22 | gdk = "^0.15" 23 | gdk-pixbuf = "^0.15" 24 | gtk = { version = "^0.15" } 25 | 26 | -------------------------------------------------------------------------------- /data/rdm.dbus: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /rdm-greeter/src/constants.rs: -------------------------------------------------------------------------------- 1 | /* BASE CONSTANTS */ 2 | pub const APPLICATION_NAME: &str = "rdm-greeter"; 3 | 4 | /* -- THEME SETTINGS -- */ 5 | pub const THEME_BASE_PATH: &str = "/usr/share/rdm/themes/"; 6 | 7 | pub const THEME_MAIN_FILE_NAME: &str = "rdm"; 8 | pub const THEME_MAIN_FILE_EXT: &str = "theme"; 9 | 10 | pub const THEME_BACKGROUND_NAME: &str = "background"; 11 | pub const THEME_BACKGROUND_EXT: &str = "png"; 12 | 13 | pub const THEME_COMPONENT_WINDOW: &str = "window"; 14 | pub const THEME_COMPONENT_BG: &str = "background"; 15 | pub const THEME_COMPONENT_USER: &str = "user"; 16 | pub const THEME_COMPONENT_SECRET: &str = "secret"; 17 | 18 | pub const THEME_NAME_DEFAULT: &str = "default"; 19 | 20 | /* -- KEYVALS -- */ 21 | pub const KEYVAL_ENTER: u32 = 0xFF0D; 22 | -------------------------------------------------------------------------------- /rdm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rdm" 3 | version = "0.0.1" 4 | authors = ["Florian Wilkens "] 5 | description = "Simple Display Manager inspired by SLiM" 6 | repository = "https://github.com/1wilkens/rdm" 7 | readme = "README.md" 8 | license = "MIT" 9 | 10 | edition = "2018" 11 | 12 | [dependencies] 13 | rdmcommon = { path = "../libcommon"} 14 | 15 | futures = "^0.3" 16 | tokio = { version = "^1.5", features = ["full"] } 17 | tokio-util = { version = "^0.7", features = ["codec"]} 18 | 19 | slog = "^2.0" 20 | slog-async = "^2.0" 21 | slog-term = "^2.0" 22 | clap = "^2.29" 23 | rand = "^0.8" 24 | uuid = { version = "^1.1", features = ["v4"] } 25 | 26 | dbus = "^0.9" 27 | dbus-tokio = "^0.7" 28 | pam = "^0.7" 29 | libc = "^0.2" 30 | users = "^0.8" 31 | -------------------------------------------------------------------------------- /libcommon/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fmt; 3 | use std::io; 4 | 5 | #[derive(Debug)] 6 | pub enum IpcError { 7 | IO(io::Error), 8 | HeaderTooShort, 9 | InvalidMagic, 10 | UnknownMessageType, 11 | } 12 | 13 | impl Error for IpcError { 14 | fn description(&self) -> &str { 15 | "test" 16 | } 17 | 18 | fn cause(&self) -> Option<&(dyn Error)> { 19 | match *self { 20 | IpcError::IO(ref err) => Some(err), 21 | _ => None, 22 | } 23 | } 24 | } 25 | 26 | impl From for IpcError { 27 | fn from(error: io::Error) -> Self { 28 | IpcError::IO(error) 29 | } 30 | } 31 | 32 | impl fmt::Display for IpcError { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | write!(f, "test") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: install clean check clippy 2 | 3 | CC = cargo 4 | 5 | all: dbg 6 | 7 | dbg: 8 | $(CC) build 9 | 10 | check: 11 | $(CC) check 12 | 13 | clippy: 14 | $(CC) clippy 15 | 16 | run: dbg 17 | $(shell sudo target/debug/rdm) 18 | 19 | rdm: 20 | $(CC) build --release 21 | 22 | install: #rdm 23 | # Copy themes 24 | $(shell sudo mkdir -p /usr/share/rdm/themes/default/) 25 | $(shell sudo cp -f theme/background.png /usr/share/rdm/themes/default/) 26 | $(shell sudo cp -f theme/rdm.theme /usr/share/rdm/themes/default/) 27 | # Copy PAM file 28 | $(shell sudo cp -f data/rdm.pam /etc/pam.d/rdm) 29 | # Copy systemd service file 30 | $(shell sudo cp -f data/rdm.service /usr/lib/systemd/system) 31 | # Copy dbus file (not required for now) 32 | #$(shell sudo cp -f data/rdm.dbus /etc/dbus-1/system.d/rdm.conf) 33 | # Copy binary 34 | $(shell sudo cp -rf target/release/rdm /usr/local/bin) 35 | 36 | clean: 37 | $(CC) clean 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2019 Florian Wilkens 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rdm-greeter/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate slog; 3 | 4 | #[allow(dead_code)] 5 | mod constants; 6 | mod ui; 7 | 8 | use std::{io::stdin, rc::Rc, sync::Mutex}; 9 | 10 | use slog::{Drain, Logger}; 11 | use slog_async::Async; 12 | use slog_term::{FullFormat, TermDecorator}; 13 | 14 | fn setup_logger() -> Logger { 15 | let decor = TermDecorator::new().build(); 16 | let drain = FullFormat::new(decor).build().fuse(); 17 | let drain = Async::new(drain).build().fuse(); 18 | let log = Logger::root(drain, o!()); 19 | debug!(&log, "[setup_logger] Initialized logging"); 20 | log 21 | } 22 | 23 | #[tokio::main] 24 | async fn main() { 25 | let log = setup_logger(); 26 | 27 | let _greeter = rdmgreeter::RdmGreeter::new(log.clone()) 28 | .await 29 | .expect("Failed to get greeter"); 30 | debug!(&log, "[main] Got greeter! Press any key to to continue"); 31 | let mut res = String::new(); 32 | let _c = stdin().read_line(&mut res); 33 | return; 34 | 35 | // Init gtk 36 | (::gtk::init()).expect("Failed to initialize gtk"); 37 | 38 | // Setup the Ui 39 | /*let mut ui = ui::Ui::from_theme(constants::THEME_NAME_DEFAULT, greeter); 40 | ui.show();*/ 41 | 42 | // Start gtk event loop 43 | ::gtk::main(); 44 | } 45 | -------------------------------------------------------------------------------- /docs/questions.md: -------------------------------------------------------------------------------- 1 | # **[rdm]** -- questions.md 2 | 3 | ## .Xauthority 4 | - Generated by dm (either by `xauth` or directly) 5 | - Don't rely on `xauth` as it may not be installed 6 | - For format of the file see: https://github.com/aosm/X11/blob/f2829c6974ac3aacdf0c5e3f1d1c2818301cec0d/xc/lib/Xau/AuWrite.c#L55 7 | - Passed to Xorg call 8 | - Persisted in `%HOME/.Xauthority` (usually) to allow access for apps + location saved in "XAUTHORITY" env var 9 | - Where to do this? 10 | - Generate pre X spawn -> pass to X 11 | - But no user yet -> share with user session which then writes to home (probably in memory) 12 | 13 | ## Dbus 14 | - Required? 15 | - Probably not strictly, but figure out which best practices exist (e.g. comply with Gnome interface) 16 | 17 | ## PAM 18 | - rdm 19 | - `system-login`? 20 | - rdm-greeter 21 | - Opens sessions -> "`-session optional pam_systemd.so`" 22 | - sddm: Cannot change password? 23 | 24 | ## Systemd 25 | - What are the requirements? 26 | - `pam_systemd.so` does not seem to be enough 27 | - How to properly validate? 28 | - Existence of user run directory not sufficient 29 | 30 | ## Other 31 | - Signalhandling? 32 | - Is the raw C API safe enough? 33 | - Are there new wrappers? 34 | - yes! tokio_signal -> investigate 35 | - Non-root Xorg 36 | - How to decide which user to run the server as? 37 | - What are the actual requirements for this? 38 | - C Callback interaction (?? migrated from `architecture.md`) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rdm [![Build Status](https://travis-ci.org/1wilkens/rdm.svg)](https://travis-ci.org/1wilkens/rdm) 2 | A display manager written in Rust. Inspired by Slim it aims to provide a simple and elegant login screen. 3 | 4 | THIS IS A WIP AND HAS MAJOR ISSUES RELATED TO SECURITY!! USE AT YOUR OWN RISK! 5 | 6 | ## Current Problems/Questions 7 | - X authorization 8 | - xauth cookie is generated but 9 | - not copied to `~/.Xauthority` 10 | - `XAUTHORITY` environment variable is not set 11 | - -> Investigate "best practices" and fix! 12 | - Session setup / PAM usage 13 | - Session setup works(tm) but I am still not sure whether all "best practices" are followed 14 | - -> Review and validate `pam-sys`/`pam-auth` crates 15 | - `reboot`/`poweroff` etc. fail with 16 | `Failed to power off system via logind: Interactive authentication required.` 17 | - -> Investigate whether this has something to do with systemd 18 | - `systemd-logind` support 19 | - Investigate what this actually means 20 | - Do we need to link against `libsystemd.so` and call APIs from there? 21 | - Implement or mark it as done 22 | - `dbus` support 23 | - Is this required (maybe for systemd integration)? 24 | - If so what methods do we need to support? 25 | - (multi-)`seat`-API 26 | - Architecture 27 | - Stay with simple client or use server-client to encapsulate login process 28 | - Likely related to multiseat support 29 | - Split into more crates (likely not justified) 30 | 31 | ## Goals 32 | - [ ] Support common standards 33 | - [x] Linux PAM (in review) 34 | - [ ] `systemd-logind` (?) 35 | - [ ] `dbus` (?) 36 | - [ ] Basic theming support 37 | -------------------------------------------------------------------------------- /docs/other_dms.md: -------------------------------------------------------------------------------- 1 | # other_dms.md 2 | 3 | ## lightdm 4 | 5 | ### General 6 | 7 | - [Design](https://www.freedesktop.org/wiki/Software/LightDM/Design/L) 8 | - Provides DBUS service 9 | - Aquires seats via logind (DBUS) exclusively?! 10 | 11 | ### Hierarchy 12 | 13 | - main.c 14 | - display\_manager\_new 15 | - seat_start 16 | - seat\_real\_start 17 | - display\_server\_start 18 | 19 | ## SDDM 20 | 21 | ### General 22 | 23 | - Provides DBUS service 24 | 25 | ## Hierarchy 26 | 27 | - DaemonApp 28 | - SeatManager 29 | - Seat 30 | - Display 31 | - DisplayServer 32 | 33 | ## GDM 34 | 35 | ### General 36 | 37 | - [Wayland progress](https://wiki.gnome.org/Initiatives/Wayland/gdm) 38 | 39 | ### daemon/main.c - `main` 40 | 41 | - block sigusr1 42 | - set locale? 43 | - parse options 44 | - check root 45 | - init logging 46 | - init settings 47 | - lookup user 48 | - names from settings 49 | - ensure dirs 50 | - sets up `/var/run/gdm`, `/var/log/gdm` 51 | - connects DBUS (`bus_reconnect`) 52 | - creates `g_main_loop` 53 | - SIGTERM, SIGINT -> `on_shutdown_signal_cb` 54 | - SIGHUP -> `on_sighup_cb` 55 | - runs main loop 56 | - < RUNNING > 57 | - shutdown settings 58 | - shutdown log 59 | 60 | ### daemon/main.c - `bus_reconnect` 61 | 62 | - get system bus 63 | - own name 64 | - `on_name_acquired` -> spin up manager object, set `show_local_greeter` and `xdmcp_enabled` and start the manager 65 | - `on_name_lost` -> cleanup manager instance and setup reconnect in 3 seconds 66 | 67 | ### daemon/gdm-manager.c - `gdm_manager_start` 68 | 69 | - if !xdmcp || show_local_greeter => gdm_display_factory_start 70 | 71 | ### daemon/gdm-display-factory.c - `gdm_display_factory_start` 72 | 73 | - TODO 74 | -------------------------------------------------------------------------------- /rdm/src/constants.rs: -------------------------------------------------------------------------------- 1 | /* BASE CONSTANTS */ 2 | pub const APPLICATION_NAME: &str = "rdm"; 3 | 4 | /* DBUS CONSTANTS */ 5 | pub const DBUS_SERVICE_NAME: &str = "com.github.1wilkens.RDM"; 6 | pub const DBUS_ROOT_PATH: &str = "com/github/1wilkens/RDM"; 7 | 8 | /* -- CONFIG SETTINGS -- */ 9 | pub const DEFAULT_CONFIG_FILE: &str = "/etc/rdm.conf"; 10 | pub const DEFAULT_RUN_DIR: &str = "/var/run/rdm"; 11 | pub const DEFAULT_SESSION_LOG_FILE: &str = "session.log"; 12 | 13 | // Change this to prevent automatic X server start e.g. 14 | pub const TESTING: bool = false; 15 | 16 | /* -- EXECUTABLES / DIRECTORIES -- */ 17 | pub const SH_EXECUTABLE: &str = "/bin/sh"; 18 | pub const X_EXECUTABLE: &str = "/usr/bin/X"; 19 | pub const XAUTH_EXECUTABLE: &str = "/usr/bin/xauth"; 20 | 21 | pub const XSESSIONS_DIRECTORY: &str = "/usr/share/xsessions"; 22 | 23 | /* -- X SERVER SETTINGS --*/ 24 | pub const X_DEFAULT_ARGS: [&str; 5] = ["-nolisten", "tcp", "-logverbose", "75", "-noreset"]; 25 | pub const X_DEFAULT_DISPLAY: &str = ":0"; 26 | pub const X_DEFAULT_VT: &str = "vt01"; 27 | pub const X_ARG_AUTH: &str = "-auth"; 28 | pub const X_ARG_DISPLAY_FD: &str = "-displayfd"; 29 | pub const X_AUTHORITY_FILE: &str = ".Xauthority"; 30 | 31 | /* -- THEME SETTINGS -- */ 32 | pub const THEME_BASE_PATH: &str = "/usr/share/rdm/themes/"; 33 | 34 | pub const THEME_MAIN_FILE_NAME: &str = "rdm"; 35 | pub const THEME_MAIN_FILE_EXT: &str = "theme"; 36 | 37 | pub const THEME_BACKGROUND_NAME: &str = "background"; 38 | pub const THEME_BACKGROUND_EXT: &str = "png"; 39 | 40 | pub const THEME_COMPONENT_WINDOW: &str = "window"; 41 | pub const THEME_COMPONENT_BG: &str = "background"; 42 | pub const THEME_COMPONENT_USER: &str = "user"; 43 | pub const THEME_COMPONENT_SECRET: &str = "secret"; 44 | 45 | pub const THEME_NAME_DEFAULT: &str = "default"; 46 | 47 | /* -- KEYVALS -- */ 48 | pub const KEYVAL_ENTER: u32 = 0xFF0D; 49 | -------------------------------------------------------------------------------- /rdm/src/bus.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Read, Write}; 2 | use std::sync::Arc; 3 | use std::thread; 4 | use std::time::Duration; 5 | 6 | use dbus::{nonblock::Proxy, Path}; 7 | use dbus_tokio::connection; 8 | use futures::prelude::*; 9 | use slog::Logger; 10 | use tokio_util::codec::Framed; 11 | 12 | use rdmcommon::{ipc, util}; 13 | 14 | pub struct BusManager { 15 | log: Logger, 16 | conn: Arc, 17 | } 18 | 19 | impl BusManager { 20 | pub fn new>>(logger: L) -> Result> { 21 | let log = logger.into().unwrap_or_else(util::plain_logger); 22 | 23 | debug!(log, "[BusManager::new] Connecting to dbus"); 24 | // Connect to the D-Bus session bus (this is blocking, unfortunately). 25 | let (resource, conn) = connection::new_system_sync()?; 26 | 27 | // The resource is a task that should be spawned onto a tokio compatible 28 | // reactor ASAP. If the resource ever finishes, you lost connection to D-Bus. 29 | tokio::spawn(async { 30 | // FIXME: we should handle this gracefully 31 | let err = resource.await; 32 | panic!("[BusManager] Lost connection to D-Bus: {}", err); 33 | }); 34 | 35 | Ok(BusManager { log, conn }) 36 | } 37 | 38 | pub async fn run(&mut self) -> Result<(), ()> { 39 | let conn = self.conn.clone(); 40 | let proxy = Proxy::new( 41 | "org.freedesktop.login1", 42 | "/org/freedesktop/login1", 43 | Duration::from_secs(2), 44 | conn, 45 | ); 46 | // TODO: Handle timeouts and errors here 47 | let (res,): (Vec<(String, Path<'_>)>,) = proxy 48 | .method_call("org.freedesktop.login1.Manager", "ListSeats", ()) 49 | .await 50 | .unwrap(); 51 | println!("{:?}", res); 52 | for (x, y) in res { 53 | debug!(&self.log, "{:?},{:?}", x, y); 54 | } 55 | Ok(()) 56 | } 57 | } 58 | 59 | impl Drop for BusManager { 60 | fn drop(&mut self) { 61 | debug!(&self.log, "Dropping BusManager"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rdm/src/ipc.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Read, Write}; 2 | use std::net::Shutdown; 3 | use std::os::unix::io::{AsRawFd, FromRawFd}; 4 | use std::sync::Arc; 5 | use std::thread; 6 | 7 | use futures::prelude::*; 8 | use slog::Logger; 9 | use tokio::io::{AsyncReadExt, AsyncWriteExt}; 10 | use tokio::net::{UnixListener, UnixStream}; 11 | use tokio_util::codec::Framed; 12 | 13 | use rdmcommon::{ipc, util}; 14 | 15 | pub struct IpcService(Logger); 16 | 17 | pub struct IpcManager { 18 | log: Logger, 19 | listener: UnixListener, 20 | } 21 | 22 | impl IpcManager { 23 | pub fn new>>(logger: L) -> Result { 24 | let log = logger.into().unwrap_or_else(util::plain_logger); 25 | 26 | debug!(log, "[IpcManager::new] Binding IPC socket"); 27 | let listener = UnixListener::bind("/home/florian/tmp/sock")?; 28 | 29 | Ok(IpcManager { log, listener }) 30 | } 31 | 32 | pub async fn run(&mut self) -> Result<(), ipc::IpcError> { 33 | match self.listener.accept().await { 34 | Ok((stream, _addr)) => self.handle(stream).await, 35 | Err(e) => { 36 | error!(&self.log, "[IpcManager::run] Error accepting unix listener"); 37 | Err(ipc::IpcError::IO(e)) 38 | } 39 | } 40 | } 41 | 42 | async fn handle(&mut self, stream: UnixStream) -> Result<(), ipc::IpcError> { 43 | debug!(&self.log, "[IpcManager::handle] New client"); 44 | let (mut writer, mut reader) = Framed::new(stream, ipc::IpcMessageCodec).split(); 45 | 46 | let req = match reader.next().await { 47 | Some(m) => m, 48 | // FIXME: extend IpcError with something like premature termination 49 | None => return Ok(()), 50 | }; 51 | let resp = match req? { 52 | ipc::IpcMessage::ClientHello => ipc::IpcMessage::ServerHello, 53 | _ => return Err(ipc::IpcError::UnknownMessageType), 54 | }; 55 | writer.send(resp).await 56 | } 57 | } 58 | 59 | impl Drop for IpcManager { 60 | fn drop(&mut self) { 61 | debug!(&self.log, "Dropping IpcManager"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /libgreeter/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::redundant_field_names)] 2 | 3 | #[macro_use] 4 | extern crate slog; 5 | 6 | extern crate tokio; 7 | 8 | use futures::prelude::*; 9 | use slog::Logger; 10 | use tokio::net::UnixStream; 11 | use tokio_util::codec::Framed; 12 | 13 | use std::io; 14 | 15 | use rdmcommon::ipc::{IpcError, IpcMessage, IpcMessageCodec}; 16 | use rdmcommon::util; 17 | 18 | pub struct RdmGreeter { 19 | log: Logger, 20 | rx: Box>>, 21 | tx: Box>, 22 | } 23 | 24 | #[derive(Debug)] 25 | pub enum RdmGreeterError { 26 | Ipc(IpcError), 27 | Io(io::Error), 28 | FailedHandshake, 29 | } 30 | 31 | impl From for RdmGreeterError { 32 | fn from(err: io::Error) -> RdmGreeterError { 33 | RdmGreeterError::Io(err) 34 | } 35 | } 36 | 37 | impl From for RdmGreeterError { 38 | fn from(err: IpcError) -> RdmGreeterError { 39 | RdmGreeterError::Ipc(err) 40 | } 41 | } 42 | 43 | impl RdmGreeter { 44 | pub async fn new>>(logger: L) -> Result { 45 | // XXX: Reenable this when tokio-async-await is updated 46 | let log = logger.into().unwrap_or_else(util::plain_logger); 47 | debug!(log, "[RdmGreeter::new] Connecting server socket"); 48 | let sock = UnixStream::connect("/home/florian/tmp/sock").await?; 49 | let (mut tx, mut rx) = Framed::new(sock, IpcMessageCodec).split(); 50 | 51 | debug!(log, "[RdmGreeter::new] Sending ClientHello"); 52 | tx.send(IpcMessage::ClientHello).await?; 53 | 54 | debug!(log, "[RdmGreeter::new] Reading server response"); 55 | let resp = match rx.next().await { 56 | Some(m) => m, 57 | // FIXME: extend IpcError with something like premature termination 58 | None => return Err(RdmGreeterError::FailedHandshake), 59 | }; 60 | debug!(log, "[RdmGreeter::new] Got server response"; "response" => ?resp); 61 | 62 | match resp? { 63 | IpcMessage::ServerHello => Ok(RdmGreeter { 64 | rx: Box::new(rx), 65 | tx: Box::new(tx), 66 | log, 67 | }), 68 | _ => Err(RdmGreeterError::FailedHandshake), 69 | } 70 | } 71 | } 72 | 73 | impl Drop for RdmGreeter { 74 | fn drop(&mut self) { 75 | debug!(self.log, "[RdmGreeter::drop] Dropping RdmGreeter.."); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /rdm/src/manager.rs: -------------------------------------------------------------------------------- 1 | /*use std::io::Write; 2 | 3 | use dbus::{BusType, Connection, ConnectionItem, Error, Message, MessageItem, NameFlag}; 4 | use dbus::obj::{Argument, Interface, Method, ObjectPath, Property}; 5 | 6 | use constants::*; 7 | 8 | pub struct Manager { 9 | running: bool, 10 | } 11 | 12 | impl Manager { 13 | pub fn new() -> Manager { 14 | Manager { running: false } 15 | } 16 | 17 | pub fn start(self) { 18 | let conn = match Connection::get_private(BusType::System) { 19 | Ok(c) => c, 20 | Err(e) => panic!("Manager: Failed to get DBUS connection: {:?}", e), 21 | }; 22 | info!("Manager: Opened {:?}", conn); 23 | 24 | conn.register_name(DBUS_SERVICE_NAME, NameFlag::ReplaceExisting as u32).unwrap(); 25 | info!("Manager: Registered service name {}", DBUS_SERVICE_NAME); 26 | 27 | let root_iface = Interface::new(vec![Method::new("Hello", 28 | vec![], 29 | vec![Argument::new("reply", "s")], 30 | Box::new(|msg| { 31 | Ok(vec!(MessageItem::Str(format!("Hello {}!", msg.sender().unwrap())))) 32 | }))], 33 | vec![], 34 | vec![]); 35 | let mut root_path = ObjectPath::new(&conn, "/", true); 36 | root_path.insert_interface(DBUS_ROOT_PATH, root_iface); 37 | root_path.set_registered(true).unwrap(); 38 | info!("Manager: Registered interface!"); 39 | 40 | info!("Manager: Starting main loop!"); 41 | for n in conn.iter(1) { 42 | if let ConnectionItem::MethodCall(mut m) = n { 43 | if root_path.handle_message(&mut m).is_none() { 44 | conn.send(Message::new_error(&m, 45 | "org.freedesktop.DBus.Error.Failed", 46 | "Object path not found") 47 | .unwrap()) 48 | .unwrap(); 49 | info!("Path not found"); 50 | } else { 51 | info!("Handled method call!"); 52 | } 53 | }; 54 | } 55 | info!("Manager: Quit main loop. Exiting.."); 56 | } 57 | }*/ -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | # **[rdm]** -- architecture.md 2 | 3 | ## General 4 | 5 | - Libraries/Technologies 6 | - `systemd`/`logind` 7 | - `DBUS` 8 | - Communication with `logind` 9 | - Multiprocess (Daemon <=> Greeter) 10 | - Communication via unix socket in `/var/run/rdm/ipc.socket` 11 | - Library for greeter 12 | - Rust 13 | - C (wrapping Rust) 14 | - React to session close => show new greeter (DBUS?) 15 | - OOP (SDDM) vs flat architecture (lightdm, gdm) 16 | - Which one is more "rusty"? 17 | - OOP 18 | - Main executable (`rdm`) launches sub 'Managers' 19 | - SeatManager 20 | - DisplayManager 21 | - PowerManager? 22 | - [+] Clear-cut separation of concerns (easier to reason about?) 23 | - [--] More complexity (`Traits` vs `structs`) 24 | - Questions 25 | - How to link managers? (Callbacks?, Fn(Once) & friends) / How does this work with struct methods? 26 | - flat 27 | - `main` sets up different features sequentially 28 | - Logging 29 | - IPC 30 | - (Dbus) 31 | - [+] All objects in scope 32 | - [+] Less complexity? (especially in regards to lifetimes) 33 | - [--] Long `main` function 34 | - `Tokio` for IPC and event loop? 35 | - Does the daemon need a real event loop? (e.g. multiplex DBUS, greeter IPC and systemd) - probably 36 | - One Greeter implementation initially (`GTK` based) 37 | 38 | ## Daemon 39 | 40 | - Responsibilities 41 | - Manage event loop with the following components 42 | - IPC socket 43 | - DBUS: Monitor logind 44 | - DBUS: Own API (maybe v2 and behind feature flag?) 45 | - Signals? 46 | - Spawn session helpers for successful logins 47 | - Monitor sessions and spawn new greeter after session ends 48 | 49 | ## Greeter 50 | 51 | - Responsibilities 52 | - Obtain credentials from user 53 | - Feed credentials to daemon 54 | - Just exit or interact with session helper? 55 | - GTK based 56 | - Theme is GTK-.xml 57 | - Mandatory input fields identified via names 58 | - Single background image (initially) named `background.png` 59 | - Connects to socket 60 | - For more customization move credential closures into theme (taking `void*` as interface pointer?) 61 | 62 | ## Authentication/Session management 63 | 64 | - Use new process for each pam authentication process as `systemd` maps pid to sessions/users 65 | - daemon: get credentials from greeter => spawn session-helper 66 | - session-helper: get credentials from daemon 67 | - authenticate against pam 68 | - spawn user session (if successful) 69 | - wait for user session to exit 70 | - cleanup and exit 71 | - Credential flow: Greeter => Daemon => Session-helper (transient) => Session 72 | - Which process uses which pam file? 73 | - Additional policy file required to start logind session? (`/etc/dbus-1/systemd./rdm.conf` ??) 74 | -------------------------------------------------------------------------------- /libcommon/src/ipc.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut, BytesMut}; 2 | use tokio_util::codec::{Decoder, Encoder}; 3 | 4 | pub use super::error::IpcError; 5 | 6 | pub const MAGIC: i16 = ((b'1' as i16) << 8) as i16 + b'w' as i16; 7 | pub const HEADER_SIZE: usize = 8; 8 | 9 | #[derive(Debug, Clone)] 10 | pub enum IpcMessage { 11 | ClientHello, 12 | ServerHello, 13 | ClientBye, 14 | RequestAuthentication(String, String), 15 | } 16 | 17 | #[derive(Debug)] 18 | pub struct IpcMessageCodec; 19 | 20 | type DecodeResult = Result, IpcError>; 21 | 22 | impl IpcMessage { 23 | pub fn message_type(&self) -> &[u8; 2] { 24 | match *self { 25 | IpcMessage::ClientHello => b"CH", 26 | IpcMessage::ServerHello => b"SH", 27 | IpcMessage::ClientBye => b"CB", 28 | IpcMessage::RequestAuthentication(ref _a, ref _b) => b"RA", 29 | } 30 | } 31 | } 32 | 33 | impl Encoder for IpcMessageCodec { 34 | type Error = IpcError; 35 | 36 | fn encode(&mut self, msg: IpcMessage, dst: &mut BytesMut) -> Result<(), Self::Error> { 37 | let len = match msg { 38 | IpcMessage::ClientHello | IpcMessage::ServerHello | IpcMessage::ClientBye => 0, 39 | IpcMessage::RequestAuthentication(ref user, ref secret) => { 40 | user.len() + secret.len() + 8 41 | } 42 | _ => return Err(IpcError::UnknownMessageType), 43 | }; 44 | 45 | dst.reserve(HEADER_SIZE + len); 46 | dst.put_i16(MAGIC); 47 | dst.extend(msg.message_type()); 48 | dst.put_u32(len as u32); 49 | 50 | if let IpcMessage::RequestAuthentication(ref user, ref secret) = msg { 51 | dst.put_u32(user.len() as u32); 52 | dst.extend(user.as_bytes()); 53 | dst.put_u32(secret.len() as u32); 54 | dst.extend(secret.as_bytes()); 55 | } 56 | 57 | Ok(()) 58 | } 59 | } 60 | 61 | impl Decoder for IpcMessageCodec { 62 | type Item = IpcMessage; 63 | type Error = IpcError; 64 | 65 | fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { 66 | match decode(buf, 0) { 67 | Ok(None) => Ok(None), 68 | Ok(Some((item, pos))) => { 69 | buf.advance(pos); 70 | Ok(Some(item)) 71 | } 72 | Err(e) => Err(e), 73 | } 74 | } 75 | } 76 | 77 | fn decode(buf: &mut BytesMut, idx: usize) -> DecodeResult { 78 | let length = buf.len(); 79 | if length <= idx { 80 | return Ok(None); 81 | } 82 | 83 | if length < HEADER_SIZE { 84 | return Err(IpcError::HeaderTooShort); 85 | } 86 | 87 | let magic = &buf[idx..idx + 2]; 88 | if magic[0] != b'1' || magic[1] != b'w' { 89 | return Err(IpcError::InvalidMagic); 90 | } 91 | 92 | let message_type = &buf[idx + 2..idx + 4]; 93 | match message_type { 94 | b"CH" => Ok(Some((IpcMessage::ClientHello, idx + HEADER_SIZE))), 95 | b"SH" => Ok(Some((IpcMessage::ServerHello, idx + HEADER_SIZE))), 96 | b"CB" => Ok(Some((IpcMessage::ClientBye, idx + HEADER_SIZE))), 97 | _ => Err(IpcError::UnknownMessageType), 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /theme/rdm.theme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 00 7 | False 8 | center 9 | 800 10 | 600 11 | desktop 12 | False 13 | 14 | 15 | True 16 | False 17 | 18 | 19 | True 20 | False 21 | 0.49000000953674316 22 | 23 | 24 | 25 | 26 | True 27 | False 28 | 0.93000000000000005 29 | center 30 | center 31 | vertical 32 | 33 | 34 | True 35 | True 36 | center 37 | center 38 | 0.5 39 | Username 40 | 41 | 42 | False 43 | True 44 | 0 45 | 46 | 47 | 48 | 49 | True 50 | True 51 | center 52 | center 53 | False 54 | * 55 | 0.5 56 | Password 57 | password 58 | 59 | 60 | False 61 | True 62 | 1 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /rdm/src/main.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(unused_imports, dead_code)] 3 | #![allow(clippy::useless_format, clippy::redundant_field_names)] 4 | 5 | #[macro_use] 6 | extern crate clap; 7 | #[macro_use] 8 | extern crate slog; 9 | 10 | mod bus; 11 | mod constants; 12 | mod ipc; 13 | mod server; 14 | mod session; 15 | 16 | use crate::constants::*; 17 | 18 | use std::io::{Read, Write}; 19 | use std::process::{exit, Child, Command}; 20 | 21 | use clap::{App, Arg, ArgMatches}; 22 | use slog::{Drain, Logger}; 23 | use slog_async::Async; 24 | use slog_term::{FullFormat, TermDecorator}; 25 | 26 | use tokio::signal::{ 27 | ctrl_c, 28 | unix::{signal, SignalKind}, 29 | }; 30 | use tokio::time::{self, Duration}; 31 | 32 | //fn test_dbus(log: &Logger) { 33 | // let conn = match Connection::get_private(BusType::System) { 34 | // Ok(c) => c, 35 | // Err(e) => panic!("Manager: Failed to get DBUS connection: {:?}", e), 36 | // }; 37 | // 38 | // let conn_path = conn.with_path("org.freedesktop.login1", "/org/freedesktop/login1", 1000); 39 | // let seats = conn_path.list_seats().expect("Failed to list seats"); 40 | // debug!(log, "Got Seats"; "seats" => ?seats); 41 | // for (name, path) in seats { 42 | // debug!(log, "Found seat"; "name" => name, "path" => ?path); 43 | // } 44 | //} 45 | 46 | fn setup_logger() -> Logger { 47 | let decor = TermDecorator::new().build(); 48 | let drain = FullFormat::new(decor).build().fuse(); 49 | let drain = Async::new(drain).build().fuse(); 50 | Logger::root(drain, o!()) 51 | } 52 | 53 | #[tokio::main] 54 | async fn main() -> Result<(), String> { 55 | let matches = App::new("rdm") 56 | .version(clap::crate_version!()) 57 | .author(clap::crate_authors!()) 58 | .about(clap::crate_description!()) 59 | .arg( 60 | Arg::with_name("verbose") 61 | .short("v") 62 | .long("verbose") 63 | .help("Enable verbose output"), 64 | ) 65 | .get_matches(); 66 | 67 | let log = setup_logger(); 68 | info!(&log, "[main] Initialized logging"); 69 | 70 | let mut bus = bus::BusManager::new(log.clone()).expect("Failed to init dbus"); 71 | info!(&log, "[main] Initialized DBus"); 72 | 73 | // XXX: Introduce error type with from conversion 74 | //let conn = 75 | // Connection::get_private(BusType::System).map_err(|_| "Failed to get DBUS connection")?; 76 | 77 | /*let conn = 78 | Connection::get_private(BusType::System).map_err(|_| "Failed to get DBUS connection")?; 79 | let foo = dbus::Manager::from_conn(conn).map_err(|_| "Failed to get DBUS connection")?;*/ 80 | 81 | // XXX: Lets start this simple 82 | // 1. init logging and read config 83 | // 2. init ipc socket (and start listening?) 84 | // 3. start x 85 | // 4. start greeter (binary from config?) 86 | // 5. auth 87 | // 6. start session (and kill x?) 88 | // 7. wait for session exit -> goto 3 89 | // 90 | 91 | let mut ipc = ipc::IpcManager::new(log.clone()).expect("Failed to init ipc"); 92 | info!(&log, "[main] Initialized IPC"); 93 | 94 | let mut signals = 95 | signal(SignalKind::hangup()).map_err(|_| "Failed to setup signal handling")?; 96 | info!(&log, "[main] Entering event loop"); 97 | loop { 98 | tokio::select! { 99 | res = bus.run() => { 100 | debug!(&log, "[main] Bus result: {:?}", res); 101 | break; 102 | } 103 | res = ipc.run() => { 104 | debug!(&log, "[main] IPC result: {:?}", res); 105 | break; 106 | } 107 | _ = signals.recv() => { 108 | info!(&log, "[main] SIGHUP => reloading configuration"); 109 | } 110 | _ = ctrl_c() => { 111 | info!(&log, "[main] SIGINT => exiting"); 112 | break; 113 | } 114 | } 115 | } 116 | 117 | Ok(()) 118 | } 119 | -------------------------------------------------------------------------------- /rdm-greeter/src/ui.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::path::{Path, PathBuf}; 3 | use std::rc::Rc; 4 | 5 | use gdk::keys; 6 | use gdk_pixbuf::Pixbuf; 7 | use gtk::prelude::*; 8 | use gtk::{Builder, Entry, Image, Window}; 9 | 10 | use slog::Logger; 11 | 12 | use rdmcommon::util; 13 | use rdmgreeter::RdmGreeter; 14 | 15 | use crate::constants::*; 16 | 17 | // Regarding Rc/RefCell see: https://stackoverflow.com/a/31967816 18 | pub struct Ui { 19 | window: Window, 20 | background: Image, 21 | user: Entry, 22 | secret: Entry, 23 | greeter: RefCell, 24 | log: Logger, 25 | } 26 | 27 | #[allow(clippy::expect_fun_call)] 28 | impl Ui { 29 | pub fn from_theme>(theme_name: T, greeter: RdmGreeter) -> Rc { 30 | let theme_path = get_theme_path(theme_name, false); 31 | 32 | let mut theme_file = theme_path.clone(); 33 | theme_file.push(THEME_MAIN_FILE_NAME); 34 | theme_file.set_extension(THEME_MAIN_FILE_EXT); 35 | 36 | let mut bg_file = theme_path; 37 | bg_file.push(THEME_BACKGROUND_NAME); 38 | bg_file.set_extension(THEME_BACKGROUND_EXT); 39 | 40 | let b = Builder::from_file(theme_file.to_str().unwrap()); 41 | 42 | let window: Window = b 43 | .object(THEME_COMPONENT_WINDOW) 44 | .expect("[ui]: Failed to get main window from theme!"); 45 | let background: Image = b 46 | .object(THEME_COMPONENT_BG) 47 | .expect("[ui]: Failed to get background image from theme!"); 48 | let user: Entry = b 49 | .object(THEME_COMPONENT_USER) 50 | .expect("[ui]: Failed to get user entry from theme!"); 51 | let secret: Entry = b 52 | .object(THEME_COMPONENT_SECRET) 53 | .expect("[ui]: Failed to get secret entry from theme!"); 54 | 55 | // fit to screen dimensions 56 | //let (width, heigth) = (Screen::width(), Screen::height()); 57 | //w.set_default_size(width, heigth); 58 | 59 | //let pb = Pixbuf::from_file_at_scale(bg_file.to_str().unwrap(), width, heigth, false) 60 | let pb = Pixbuf::from_file(bg_file.to_str().unwrap()) 61 | .expect(&format!("[ui]: Failed to get background image pixbuf: {:?}", bg_file)); 62 | 63 | background.set_from_pixbuf(Some(&pb)); 64 | 65 | let instance = Rc::new(Ui { 66 | window, 67 | background, 68 | user, 69 | secret, 70 | greeter: RefCell::from(greeter), 71 | log: util::plain_logger(), 72 | }); 73 | 74 | { 75 | let secret = instance.secret.clone(); 76 | 77 | instance.user.connect_key_release_event(move |_, e| { 78 | let val = (*e).keyval(); 79 | if val == keys::constants::ISO_Enter { 80 | secret.grab_focus(); 81 | } 82 | Inhibit(true) 83 | }); 84 | } 85 | 86 | { 87 | let _i = instance.clone(); 88 | let user = instance.user.clone(); 89 | let secret = instance.secret.clone(); 90 | 91 | instance.secret.connect_key_release_event(move |_, e| { 92 | let val = (*e).keyval(); 93 | if val == keys::constants::ISO_Enter { 94 | let _user = user.text(); 95 | let _password = secret.text(); 96 | 97 | // TODO: use librdmgreeter to talk to daemon to authenticate 98 | /*i.greeter.borrow_mut().request_authentication(&user, &password);*/ 99 | } 100 | Inhibit(true) 101 | }); 102 | } 103 | 104 | instance 105 | } 106 | 107 | pub fn show(&self) { 108 | info!(self.log, "[ui]: Showing window"); 109 | self.window.show_all(); 110 | } 111 | } 112 | 113 | /*fn start_session(name: &str) { 114 | use users::os::unix::UserExt; 115 | use std::os::unix::io::AsRawFd; 116 | use std::os::unix::io::FromRawFd; 117 | use std::os::unix::process::CommandExt; 118 | 119 | info!("[ui]: Starting session"); 120 | 121 | // Setup variables 122 | let user = ::users::get_user_by_name(name) 123 | .expect(&format!("[ui]: Could not get user by name: {}!", name)); 124 | let dir = user.home_dir(); 125 | let shell = user.shell() 126 | .to_str() 127 | .expect("[ui]: Shell was not valid unicode!"); 128 | 129 | let args = format!("exec {} --login .xinitrc", shell); 130 | 131 | // Need these later in `before_exec` to setup supplimentary groups 132 | let name_c = CString::new(name).unwrap(); 133 | let uid = user.uid(); 134 | let gid = user.primary_group_id(); 135 | 136 | // Open session log file for stderr 137 | // 138 | // Currently we mirror sddm's behaviour which discards session's stdout 139 | // and redirects stderr to a log file in the home directory 140 | let stderr = File::create(format!("{}/{}", dir.to_str().unwrap(), DEFAULT_SESSION_LOG_FILE)) 141 | .map(|f| { 142 | info!("[ui]: Redirecting session's stderr to {:?}", f); 143 | unsafe { Stdio::from_raw_fd(f.as_raw_fd()) } 144 | }) 145 | .unwrap_or_else(|_| { 146 | info!("[ui]: Failed to create session log file, falling back to inherit.."); 147 | Stdio::inherit() 148 | }); 149 | 150 | // Start session loading .xinitrc 151 | info!("[ui]: Starting session"); 152 | info!("[ui]: Session command '{} -c {}'", shell, args); 153 | /*let mut child = */ 154 | Command::new(shell) 155 | // Arguments 156 | .arg("-c") 157 | .arg(args) 158 | // Process setup 159 | .current_dir(dir) 160 | // TODO: Figure out why these are set / how to properly handle them 161 | .env_remove("INVOCATION_ID") 162 | .env_remove("JOURNAL_STREAM") 163 | // Cannot use this as it does not add supplimentary groups 164 | //.uid(user.uid()) 165 | .gid(gid) 166 | .before_exec(move || { 167 | // This sets the supplimentary groups for the session 168 | if unsafe { initgroups(name_c.as_ptr(), gid) } != 0 { 169 | error!("[ui:session] initgroups returned non-zero!"); 170 | Err(Error::last_os_error()) 171 | } 172 | else if unsafe { setuid(uid) } != 0 { 173 | error!("[ui:session] setuid returned non-zero!"); 174 | Err(Error::last_os_error()) 175 | } 176 | else { 177 | Ok(()) 178 | } 179 | }) 180 | // Output redirection 181 | .stdout(Stdio::null()) 182 | .stderr(stderr) 183 | .spawn() 184 | .unwrap_or_else(|e| panic!("[ui]: Failed to start session: {}!", e)); 185 | 186 | info!("[ui]: Spawned session process & waiting for result"); 187 | 188 | //TODO: Waiting for the child causes an "invisible window" in i3.. Investigate further 189 | //let result = child.wait() 190 | // .unwrap_or_else(|e| panic!("[ui]: Failed to join session thread: {:?}!", e)); 191 | //info!("[ui]: Session exited with return code: {}", result); 192 | }*/ 193 | 194 | fn get_theme_path>(theme_name: T, default: bool) -> PathBuf { 195 | let mut theme_path = PathBuf::new(); 196 | theme_path.push(THEME_BASE_PATH); 197 | theme_path.push(theme_name); 198 | 199 | if theme_path.is_dir() { 200 | theme_path 201 | } else if !default { 202 | get_theme_path(THEME_NAME_DEFAULT, true) 203 | } else { 204 | panic!("[ui]: Could not load default configuration!") 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /rdm/src/server.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs; 3 | use std::io::{Read, Write}; 4 | use std::path::PathBuf; 5 | use std::process::{Child, Command, Stdio}; 6 | use std::thread; 7 | use std::time::Duration; 8 | 9 | use libc::{close, pipe}; 10 | use rand::{seq::SliceRandom, thread_rng}; 11 | use slog::Logger; 12 | use uuid::{ 13 | fmt::{Hyphenated, Simple}, 14 | Uuid, 15 | }; 16 | 17 | use crate::constants::*; 18 | use rdmcommon::util; 19 | 20 | // TODO: This should really be simpler I think 21 | const HEX_CHARS: [char; 16] = [ 22 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 23 | ]; 24 | 25 | pub struct Xserver { 26 | log: Logger, 27 | auth_cookie: String, 28 | auth_file: Option, 29 | process: Option, 30 | display: Option, 31 | } 32 | 33 | impl Xserver { 34 | pub fn new>>(logger: L) -> Self { 35 | let log = logger.into().unwrap_or_else(util::plain_logger); 36 | 37 | let cookie = generate_cookie(&log); 38 | debug!(log, "[X::new] Generated auth cookie: {}", &cookie); 39 | let file = touch_auth_file(&log); 40 | 41 | Xserver { 42 | log: log, 43 | auth_cookie: cookie, 44 | auth_file: Some(file), 45 | process: None, 46 | display: None, 47 | } 48 | } 49 | 50 | pub fn start(&mut self) { 51 | info!(&self.log, "[X::start]"); 52 | 53 | if TESTING { 54 | // In TESTING mode we don't start X 55 | return; 56 | } 57 | if self.process.is_some() { 58 | // X is already running -> silently return 59 | return; 60 | } 61 | 62 | // Set the previously generated auth cookie 63 | self.set_cookie(); 64 | 65 | // Launch X and wait a second for it to start 66 | self.start_x_process(); 67 | } 68 | 69 | pub fn stop(&mut self) { 70 | info!(&self.log, "[X::stop]"); 71 | 72 | // TODO: There is probably more to do here 73 | // Kill X process 74 | if let Some(ref mut p) = self.process { 75 | info!(&self.log, "[X::stop]: Killing X with PID={}", p.id()); 76 | match p.kill() { 77 | Ok(_res) => {} //info!("[X]: Killed X with Result={:?}", res), 78 | Err(_err) => {} //error!("[X]: Failed to kill X: {}", err), 79 | }; 80 | 81 | p.wait().expect("[X::stop]: Failed to wait for stopped X server!"); 82 | } 83 | self.process = None; 84 | // Delete generated auth file 85 | match self.auth_file { 86 | None => {} 87 | Some(ref f) => { 88 | match fs::remove_file(&f) { 89 | Ok(_) => {} 90 | Err(_e) => {} //info!("Failed to delete x auth file: {}", e), 91 | } 92 | } 93 | } 94 | self.auth_file = None; 95 | } 96 | 97 | fn set_cookie(&self) { 98 | info!(&self.log, "[X]: Setting auth cookie"); 99 | 100 | let auth_file = match self.auth_file { 101 | Some(ref f) => f, 102 | None => panic!("[X]: Cannot set X auth cookie without an auth file!"), 103 | }; 104 | let mut auth = Command::new(XAUTH_EXECUTABLE) 105 | .arg("-f") 106 | .arg(auth_file) 107 | .arg("-q") 108 | .stdin(Stdio::piped()) 109 | .spawn() 110 | .expect("[X]: Failed to spawn xauth process!"); 111 | 112 | if let Some(ref mut pipe) = auth.stdin { 113 | pipe.write_all(b"remove :0\n").unwrap(); 114 | pipe.write_all(format!("add :0 . {}\n", self.auth_cookie).as_bytes()) 115 | .unwrap(); 116 | pipe.write_all(b"exit\n").unwrap(); 117 | pipe.flush().expect("[X]: Failed to flush xauth pipe!"); 118 | } 119 | 120 | // Wait on xauth to prevent zombie processes 121 | auth.wait().expect("[X]: Failed to wait on xauth process!"); 122 | 123 | info!(&self.log, "[X]: Auth cookie set"); 124 | } 125 | 126 | fn start_x_process(&mut self) { 127 | use std::os::unix::io::FromRawFd; 128 | 129 | // Create pipes to read DISPLAY from X 130 | let mut fds = [0i32, 0i32]; 131 | if unsafe { pipe(fds.as_mut_ptr()) != 0 } { 132 | panic!("[X]: Failed to open pipes to start X!"); 133 | } 134 | 135 | let _auth_file = match self.auth_file { 136 | Some(ref f) => f, 137 | None => panic!("[X]: Cannot start X without an auth file!"), 138 | }; 139 | // Start X and set the field 140 | let child = Command::new(X_EXECUTABLE) 141 | // Arguments 142 | .args(&X_DEFAULT_ARGS) 143 | .arg(X_ARG_DISPLAY_FD) 144 | .arg(&fds[1].to_string()) 145 | .arg(X_DEFAULT_VT) 146 | //.arg(X_ARG_AUTH) 147 | //.arg(_auth_file) 148 | // Output redirection 149 | .stdout(Stdio::null()) 150 | .stderr(Stdio::null()) 151 | .spawn() 152 | .unwrap_or_else(|e| panic!("[X]: Failed to start X: {}!", e)); 153 | self.process = Some(child); 154 | 155 | // Wait 1 second for X to start 156 | info!(&self.log, "[X]: Started X.. Sleeping 1 second"); 157 | thread::sleep(Duration::from_millis(1000)); 158 | info!(&self.log, "[X]: Sleep finished"); 159 | 160 | // Close writing end of the pipe 161 | unsafe { close(fds[1]) }; 162 | 163 | // Read chosen DISPLAY from X and set the environment variable 164 | let mut pipe = unsafe { fs::File::from_raw_fd(fds[0]) }; 165 | let mut display = String::new(); 166 | pipe.read_to_string(&mut display) 167 | .expect("[X]: Failed to read DISPLAY from X!"); 168 | // TODO: This allocates twice but we mostly deal with "0" so it shouldn't be a problem 169 | let display = format!(":{}", display.trim_end()); 170 | env::set_var("DISPLAY", &display); 171 | debug!( 172 | &self.log, 173 | "[X]: Got DISPLAY from X and set the env var: {}", &display 174 | ); 175 | self.display = Some(display); 176 | 177 | // Close reading pipe // TODO: Is this necessary? Investigate 178 | //drop(pipe); 179 | unsafe { close(fds[0]) }; 180 | } 181 | } 182 | 183 | impl Drop for Xserver { 184 | fn drop(&mut self) { 185 | // Currently we just stop the server 186 | self.stop(); 187 | } 188 | } 189 | 190 | // Generate an authorization cookie 191 | fn generate_cookie(log: &Logger) -> String { 192 | info!(log, "[X]: Generating auth cookie"); 193 | 194 | // We use an uuid in 'simple' format aka 32 random chars 195 | Simple::from_uuid(Uuid::new_v4()).to_string() 196 | } 197 | 198 | // Generate an auth file based on the run dir and a new uuid and touch it 199 | fn touch_auth_file(log: &Logger) -> String { 200 | info!(log, "[X]: Generating auth path"); 201 | 202 | let uuid = Uuid::new_v4(); 203 | let mut path = PathBuf::from(DEFAULT_RUN_DIR); 204 | path.push(Hyphenated::from_uuid(uuid).to_string()); 205 | 206 | match fs::OpenOptions::new() 207 | .write(true) 208 | .create_new(true) 209 | .open(&path) 210 | { 211 | Ok(_) => {} 212 | Err(e) => panic!("[X]: Failed to touch X auth file: {}!", e), 213 | } 214 | 215 | debug!(log, "[X]: Generated auth file path: {:?}", &path); 216 | path.to_string_lossy().into_owned() 217 | } 218 | -------------------------------------------------------------------------------- /data/login1.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 36 | 37 | 151 | 152 | 153 | 154 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ansi_term" 7 | version = "0.12.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 10 | dependencies = [ 11 | "winapi", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.57" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" 19 | 20 | [[package]] 21 | name = "atk" 22 | version = "0.15.1" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" 25 | dependencies = [ 26 | "atk-sys", 27 | "bitflags", 28 | "glib", 29 | "libc", 30 | ] 31 | 32 | [[package]] 33 | name = "atk-sys" 34 | version = "0.15.1" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" 37 | dependencies = [ 38 | "glib-sys", 39 | "gobject-sys", 40 | "libc", 41 | "system-deps", 42 | ] 43 | 44 | [[package]] 45 | name = "atty" 46 | version = "0.2.14" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 49 | dependencies = [ 50 | "hermit-abi", 51 | "libc", 52 | "winapi", 53 | ] 54 | 55 | [[package]] 56 | name = "autocfg" 57 | version = "1.1.0" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 60 | 61 | [[package]] 62 | name = "bitflags" 63 | version = "1.3.2" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 66 | 67 | [[package]] 68 | name = "bytes" 69 | version = "1.1.0" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 72 | 73 | [[package]] 74 | name = "cairo-rs" 75 | version = "0.15.11" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "62be3562254e90c1c6050a72aa638f6315593e98c5cdaba9017cedbabf0a5dee" 78 | dependencies = [ 79 | "bitflags", 80 | "cairo-sys-rs", 81 | "glib", 82 | "libc", 83 | "thiserror", 84 | ] 85 | 86 | [[package]] 87 | name = "cairo-sys-rs" 88 | version = "0.15.1" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" 91 | dependencies = [ 92 | "glib-sys", 93 | "libc", 94 | "system-deps", 95 | ] 96 | 97 | [[package]] 98 | name = "cfg-expr" 99 | version = "0.10.3" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" 102 | dependencies = [ 103 | "smallvec", 104 | ] 105 | 106 | [[package]] 107 | name = "cfg-if" 108 | version = "1.0.0" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 111 | 112 | [[package]] 113 | name = "clap" 114 | version = "2.34.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 117 | dependencies = [ 118 | "ansi_term", 119 | "atty", 120 | "bitflags", 121 | "strsim", 122 | "textwrap", 123 | "unicode-width", 124 | "vec_map", 125 | ] 126 | 127 | [[package]] 128 | name = "crossbeam-channel" 129 | version = "0.5.4" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" 132 | dependencies = [ 133 | "cfg-if", 134 | "crossbeam-utils", 135 | ] 136 | 137 | [[package]] 138 | name = "crossbeam-utils" 139 | version = "0.8.8" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" 142 | dependencies = [ 143 | "cfg-if", 144 | "lazy_static", 145 | ] 146 | 147 | [[package]] 148 | name = "dbus" 149 | version = "0.9.5" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "de0a745c25b32caa56b82a3950f5fec7893a960f4c10ca3b02060b0c38d8c2ce" 152 | dependencies = [ 153 | "futures-channel", 154 | "futures-util", 155 | "libc", 156 | "libdbus-sys", 157 | "winapi", 158 | ] 159 | 160 | [[package]] 161 | name = "dbus-tokio" 162 | version = "0.7.5" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "12a1a74a0c53b22d7d994256cf3ecbeefa5eedce3cf9d362945ac523c4132180" 165 | dependencies = [ 166 | "dbus", 167 | "libc", 168 | "tokio", 169 | ] 170 | 171 | [[package]] 172 | name = "dirs-next" 173 | version = "2.0.0" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 176 | dependencies = [ 177 | "cfg-if", 178 | "dirs-sys-next", 179 | ] 180 | 181 | [[package]] 182 | name = "dirs-sys-next" 183 | version = "0.1.2" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 186 | dependencies = [ 187 | "libc", 188 | "redox_users", 189 | "winapi", 190 | ] 191 | 192 | [[package]] 193 | name = "field-offset" 194 | version = "0.3.4" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" 197 | dependencies = [ 198 | "memoffset", 199 | "rustc_version", 200 | ] 201 | 202 | [[package]] 203 | name = "futures" 204 | version = "0.3.21" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" 207 | dependencies = [ 208 | "futures-channel", 209 | "futures-core", 210 | "futures-executor", 211 | "futures-io", 212 | "futures-sink", 213 | "futures-task", 214 | "futures-util", 215 | ] 216 | 217 | [[package]] 218 | name = "futures-channel" 219 | version = "0.3.21" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" 222 | dependencies = [ 223 | "futures-core", 224 | "futures-sink", 225 | ] 226 | 227 | [[package]] 228 | name = "futures-core" 229 | version = "0.3.21" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" 232 | 233 | [[package]] 234 | name = "futures-executor" 235 | version = "0.3.21" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" 238 | dependencies = [ 239 | "futures-core", 240 | "futures-task", 241 | "futures-util", 242 | ] 243 | 244 | [[package]] 245 | name = "futures-io" 246 | version = "0.3.21" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" 249 | 250 | [[package]] 251 | name = "futures-macro" 252 | version = "0.3.21" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" 255 | dependencies = [ 256 | "proc-macro2", 257 | "quote", 258 | "syn", 259 | ] 260 | 261 | [[package]] 262 | name = "futures-sink" 263 | version = "0.3.21" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" 266 | 267 | [[package]] 268 | name = "futures-task" 269 | version = "0.3.21" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" 272 | 273 | [[package]] 274 | name = "futures-util" 275 | version = "0.3.21" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" 278 | dependencies = [ 279 | "futures-channel", 280 | "futures-core", 281 | "futures-io", 282 | "futures-macro", 283 | "futures-sink", 284 | "futures-task", 285 | "memchr", 286 | "pin-project-lite", 287 | "pin-utils", 288 | "slab", 289 | ] 290 | 291 | [[package]] 292 | name = "gdk" 293 | version = "0.15.4" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" 296 | dependencies = [ 297 | "bitflags", 298 | "cairo-rs", 299 | "gdk-pixbuf", 300 | "gdk-sys", 301 | "gio", 302 | "glib", 303 | "libc", 304 | "pango", 305 | ] 306 | 307 | [[package]] 308 | name = "gdk-pixbuf" 309 | version = "0.15.11" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" 312 | dependencies = [ 313 | "bitflags", 314 | "gdk-pixbuf-sys", 315 | "gio", 316 | "glib", 317 | "libc", 318 | ] 319 | 320 | [[package]] 321 | name = "gdk-pixbuf-sys" 322 | version = "0.15.10" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" 325 | dependencies = [ 326 | "gio-sys", 327 | "glib-sys", 328 | "gobject-sys", 329 | "libc", 330 | "system-deps", 331 | ] 332 | 333 | [[package]] 334 | name = "gdk-sys" 335 | version = "0.15.1" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" 338 | dependencies = [ 339 | "cairo-sys-rs", 340 | "gdk-pixbuf-sys", 341 | "gio-sys", 342 | "glib-sys", 343 | "gobject-sys", 344 | "libc", 345 | "pango-sys", 346 | "pkg-config", 347 | "system-deps", 348 | ] 349 | 350 | [[package]] 351 | name = "getrandom" 352 | version = "0.2.7" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 355 | dependencies = [ 356 | "cfg-if", 357 | "libc", 358 | "wasi", 359 | ] 360 | 361 | [[package]] 362 | name = "gio" 363 | version = "0.15.11" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "0f132be35e05d9662b9fa0fee3f349c6621f7782e0105917f4cc73c1bf47eceb" 366 | dependencies = [ 367 | "bitflags", 368 | "futures-channel", 369 | "futures-core", 370 | "futures-io", 371 | "gio-sys", 372 | "glib", 373 | "libc", 374 | "once_cell", 375 | "thiserror", 376 | ] 377 | 378 | [[package]] 379 | name = "gio-sys" 380 | version = "0.15.10" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" 383 | dependencies = [ 384 | "glib-sys", 385 | "gobject-sys", 386 | "libc", 387 | "system-deps", 388 | "winapi", 389 | ] 390 | 391 | [[package]] 392 | name = "glib" 393 | version = "0.15.11" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "bd124026a2fa8c33a3d17a3fe59c103f2d9fa5bd92c19e029e037736729abeab" 396 | dependencies = [ 397 | "bitflags", 398 | "futures-channel", 399 | "futures-core", 400 | "futures-executor", 401 | "futures-task", 402 | "glib-macros", 403 | "glib-sys", 404 | "gobject-sys", 405 | "libc", 406 | "once_cell", 407 | "smallvec", 408 | "thiserror", 409 | ] 410 | 411 | [[package]] 412 | name = "glib-macros" 413 | version = "0.15.11" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" 416 | dependencies = [ 417 | "anyhow", 418 | "heck", 419 | "proc-macro-crate", 420 | "proc-macro-error", 421 | "proc-macro2", 422 | "quote", 423 | "syn", 424 | ] 425 | 426 | [[package]] 427 | name = "glib-sys" 428 | version = "0.15.10" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" 431 | dependencies = [ 432 | "libc", 433 | "system-deps", 434 | ] 435 | 436 | [[package]] 437 | name = "gobject-sys" 438 | version = "0.15.10" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" 441 | dependencies = [ 442 | "glib-sys", 443 | "libc", 444 | "system-deps", 445 | ] 446 | 447 | [[package]] 448 | name = "gtk" 449 | version = "0.15.5" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" 452 | dependencies = [ 453 | "atk", 454 | "bitflags", 455 | "cairo-rs", 456 | "field-offset", 457 | "futures-channel", 458 | "gdk", 459 | "gdk-pixbuf", 460 | "gio", 461 | "glib", 462 | "gtk-sys", 463 | "gtk3-macros", 464 | "libc", 465 | "once_cell", 466 | "pango", 467 | "pkg-config", 468 | ] 469 | 470 | [[package]] 471 | name = "gtk-sys" 472 | version = "0.15.3" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" 475 | dependencies = [ 476 | "atk-sys", 477 | "cairo-sys-rs", 478 | "gdk-pixbuf-sys", 479 | "gdk-sys", 480 | "gio-sys", 481 | "glib-sys", 482 | "gobject-sys", 483 | "libc", 484 | "pango-sys", 485 | "system-deps", 486 | ] 487 | 488 | [[package]] 489 | name = "gtk3-macros" 490 | version = "0.15.4" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9" 493 | dependencies = [ 494 | "anyhow", 495 | "proc-macro-crate", 496 | "proc-macro-error", 497 | "proc-macro2", 498 | "quote", 499 | "syn", 500 | ] 501 | 502 | [[package]] 503 | name = "heck" 504 | version = "0.4.0" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 507 | 508 | [[package]] 509 | name = "hermit-abi" 510 | version = "0.1.19" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 513 | dependencies = [ 514 | "libc", 515 | ] 516 | 517 | [[package]] 518 | name = "itoa" 519 | version = "1.0.2" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" 522 | 523 | [[package]] 524 | name = "lazy_static" 525 | version = "1.4.0" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 528 | 529 | [[package]] 530 | name = "libc" 531 | version = "0.2.126" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" 534 | 535 | [[package]] 536 | name = "libdbus-sys" 537 | version = "0.2.2" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" 540 | dependencies = [ 541 | "pkg-config", 542 | ] 543 | 544 | [[package]] 545 | name = "lock_api" 546 | version = "0.4.7" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" 549 | dependencies = [ 550 | "autocfg", 551 | "scopeguard", 552 | ] 553 | 554 | [[package]] 555 | name = "log" 556 | version = "0.4.17" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 559 | dependencies = [ 560 | "cfg-if", 561 | ] 562 | 563 | [[package]] 564 | name = "memchr" 565 | version = "2.5.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 568 | 569 | [[package]] 570 | name = "memoffset" 571 | version = "0.6.5" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 574 | dependencies = [ 575 | "autocfg", 576 | ] 577 | 578 | [[package]] 579 | name = "mio" 580 | version = "0.8.3" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" 583 | dependencies = [ 584 | "libc", 585 | "log", 586 | "wasi", 587 | "windows-sys", 588 | ] 589 | 590 | [[package]] 591 | name = "num_cpus" 592 | version = "1.13.1" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 595 | dependencies = [ 596 | "hermit-abi", 597 | "libc", 598 | ] 599 | 600 | [[package]] 601 | name = "num_threads" 602 | version = "0.1.6" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" 605 | dependencies = [ 606 | "libc", 607 | ] 608 | 609 | [[package]] 610 | name = "once_cell" 611 | version = "1.12.0" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" 614 | 615 | [[package]] 616 | name = "pam" 617 | version = "0.7.0" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "fa2bdc959c201c047004a1420a92aaa1dd1a6b64d5ef333aa3a4ac764fb93097" 620 | dependencies = [ 621 | "libc", 622 | "pam-sys", 623 | "users", 624 | ] 625 | 626 | [[package]] 627 | name = "pam-sys" 628 | version = "0.5.6" 629 | source = "registry+https://github.com/rust-lang/crates.io-index" 630 | checksum = "cd4858311a097f01a0006ef7d0cd50bca81ec430c949d7bf95cbefd202282434" 631 | dependencies = [ 632 | "libc", 633 | ] 634 | 635 | [[package]] 636 | name = "pango" 637 | version = "0.15.10" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" 640 | dependencies = [ 641 | "bitflags", 642 | "glib", 643 | "libc", 644 | "once_cell", 645 | "pango-sys", 646 | ] 647 | 648 | [[package]] 649 | name = "pango-sys" 650 | version = "0.15.10" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" 653 | dependencies = [ 654 | "glib-sys", 655 | "gobject-sys", 656 | "libc", 657 | "system-deps", 658 | ] 659 | 660 | [[package]] 661 | name = "parking_lot" 662 | version = "0.12.1" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 665 | dependencies = [ 666 | "lock_api", 667 | "parking_lot_core", 668 | ] 669 | 670 | [[package]] 671 | name = "parking_lot_core" 672 | version = "0.9.3" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" 675 | dependencies = [ 676 | "cfg-if", 677 | "libc", 678 | "redox_syscall", 679 | "smallvec", 680 | "windows-sys", 681 | ] 682 | 683 | [[package]] 684 | name = "pest" 685 | version = "2.1.3" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" 688 | dependencies = [ 689 | "ucd-trie", 690 | ] 691 | 692 | [[package]] 693 | name = "pin-project-lite" 694 | version = "0.2.9" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 697 | 698 | [[package]] 699 | name = "pin-utils" 700 | version = "0.1.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 703 | 704 | [[package]] 705 | name = "pkg-config" 706 | version = "0.3.25" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" 709 | 710 | [[package]] 711 | name = "ppv-lite86" 712 | version = "0.2.16" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 715 | 716 | [[package]] 717 | name = "proc-macro-crate" 718 | version = "1.1.3" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" 721 | dependencies = [ 722 | "thiserror", 723 | "toml", 724 | ] 725 | 726 | [[package]] 727 | name = "proc-macro-error" 728 | version = "1.0.4" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 731 | dependencies = [ 732 | "proc-macro-error-attr", 733 | "proc-macro2", 734 | "quote", 735 | "syn", 736 | "version_check", 737 | ] 738 | 739 | [[package]] 740 | name = "proc-macro-error-attr" 741 | version = "1.0.4" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 744 | dependencies = [ 745 | "proc-macro2", 746 | "quote", 747 | "version_check", 748 | ] 749 | 750 | [[package]] 751 | name = "proc-macro2" 752 | version = "1.0.39" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" 755 | dependencies = [ 756 | "unicode-ident", 757 | ] 758 | 759 | [[package]] 760 | name = "quote" 761 | version = "1.0.18" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" 764 | dependencies = [ 765 | "proc-macro2", 766 | ] 767 | 768 | [[package]] 769 | name = "rand" 770 | version = "0.8.5" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 773 | dependencies = [ 774 | "libc", 775 | "rand_chacha", 776 | "rand_core", 777 | ] 778 | 779 | [[package]] 780 | name = "rand_chacha" 781 | version = "0.3.1" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 784 | dependencies = [ 785 | "ppv-lite86", 786 | "rand_core", 787 | ] 788 | 789 | [[package]] 790 | name = "rand_core" 791 | version = "0.6.3" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 794 | dependencies = [ 795 | "getrandom", 796 | ] 797 | 798 | [[package]] 799 | name = "rdm" 800 | version = "0.0.1" 801 | dependencies = [ 802 | "clap", 803 | "dbus", 804 | "dbus-tokio", 805 | "futures", 806 | "libc", 807 | "pam", 808 | "rand", 809 | "rdmcommon", 810 | "slog", 811 | "slog-async", 812 | "slog-term", 813 | "tokio", 814 | "tokio-util", 815 | "users", 816 | "uuid", 817 | ] 818 | 819 | [[package]] 820 | name = "rdm-greeter" 821 | version = "0.0.1" 822 | dependencies = [ 823 | "gdk", 824 | "gdk-pixbuf", 825 | "gtk", 826 | "rdmcommon", 827 | "rdmgreeter", 828 | "slog", 829 | "slog-async", 830 | "slog-term", 831 | "tokio", 832 | ] 833 | 834 | [[package]] 835 | name = "rdmcommon" 836 | version = "0.0.1" 837 | dependencies = [ 838 | "bytes", 839 | "slog", 840 | "slog-term", 841 | "tokio", 842 | "tokio-util", 843 | ] 844 | 845 | [[package]] 846 | name = "rdmgreeter" 847 | version = "0.0.1" 848 | dependencies = [ 849 | "futures", 850 | "rdmcommon", 851 | "slog", 852 | "tokio", 853 | "tokio-util", 854 | ] 855 | 856 | [[package]] 857 | name = "redox_syscall" 858 | version = "0.2.13" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" 861 | dependencies = [ 862 | "bitflags", 863 | ] 864 | 865 | [[package]] 866 | name = "redox_users" 867 | version = "0.4.3" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 870 | dependencies = [ 871 | "getrandom", 872 | "redox_syscall", 873 | "thiserror", 874 | ] 875 | 876 | [[package]] 877 | name = "rustc_version" 878 | version = "0.3.3" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" 881 | dependencies = [ 882 | "semver", 883 | ] 884 | 885 | [[package]] 886 | name = "rustversion" 887 | version = "1.0.6" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" 890 | 891 | [[package]] 892 | name = "scopeguard" 893 | version = "1.1.0" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 896 | 897 | [[package]] 898 | name = "semver" 899 | version = "0.11.0" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" 902 | dependencies = [ 903 | "semver-parser", 904 | ] 905 | 906 | [[package]] 907 | name = "semver-parser" 908 | version = "0.10.2" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" 911 | dependencies = [ 912 | "pest", 913 | ] 914 | 915 | [[package]] 916 | name = "serde" 917 | version = "1.0.137" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" 920 | 921 | [[package]] 922 | name = "signal-hook-registry" 923 | version = "1.4.0" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 926 | dependencies = [ 927 | "libc", 928 | ] 929 | 930 | [[package]] 931 | name = "slab" 932 | version = "0.4.6" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" 935 | 936 | [[package]] 937 | name = "slog" 938 | version = "2.7.0" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" 941 | 942 | [[package]] 943 | name = "slog-async" 944 | version = "2.7.0" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "766c59b252e62a34651412870ff55d8c4e6d04df19b43eecb2703e417b097ffe" 947 | dependencies = [ 948 | "crossbeam-channel", 949 | "slog", 950 | "take_mut", 951 | "thread_local", 952 | ] 953 | 954 | [[package]] 955 | name = "slog-term" 956 | version = "2.9.0" 957 | source = "registry+https://github.com/rust-lang/crates.io-index" 958 | checksum = "87d29185c55b7b258b4f120eab00f48557d4d9bc814f41713f449d35b0f8977c" 959 | dependencies = [ 960 | "atty", 961 | "slog", 962 | "term", 963 | "thread_local", 964 | "time", 965 | ] 966 | 967 | [[package]] 968 | name = "smallvec" 969 | version = "1.8.0" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" 972 | 973 | [[package]] 974 | name = "socket2" 975 | version = "0.4.4" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" 978 | dependencies = [ 979 | "libc", 980 | "winapi", 981 | ] 982 | 983 | [[package]] 984 | name = "strsim" 985 | version = "0.8.0" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 988 | 989 | [[package]] 990 | name = "syn" 991 | version = "1.0.96" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" 994 | dependencies = [ 995 | "proc-macro2", 996 | "quote", 997 | "unicode-ident", 998 | ] 999 | 1000 | [[package]] 1001 | name = "system-deps" 1002 | version = "6.0.2" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" 1005 | dependencies = [ 1006 | "cfg-expr", 1007 | "heck", 1008 | "pkg-config", 1009 | "toml", 1010 | "version-compare", 1011 | ] 1012 | 1013 | [[package]] 1014 | name = "take_mut" 1015 | version = "0.2.2" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" 1018 | 1019 | [[package]] 1020 | name = "term" 1021 | version = "0.7.0" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" 1024 | dependencies = [ 1025 | "dirs-next", 1026 | "rustversion", 1027 | "winapi", 1028 | ] 1029 | 1030 | [[package]] 1031 | name = "textwrap" 1032 | version = "0.11.0" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 1035 | dependencies = [ 1036 | "unicode-width", 1037 | ] 1038 | 1039 | [[package]] 1040 | name = "thiserror" 1041 | version = "1.0.31" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" 1044 | dependencies = [ 1045 | "thiserror-impl", 1046 | ] 1047 | 1048 | [[package]] 1049 | name = "thiserror-impl" 1050 | version = "1.0.31" 1051 | source = "registry+https://github.com/rust-lang/crates.io-index" 1052 | checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" 1053 | dependencies = [ 1054 | "proc-macro2", 1055 | "quote", 1056 | "syn", 1057 | ] 1058 | 1059 | [[package]] 1060 | name = "thread_local" 1061 | version = "1.1.4" 1062 | source = "registry+https://github.com/rust-lang/crates.io-index" 1063 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 1064 | dependencies = [ 1065 | "once_cell", 1066 | ] 1067 | 1068 | [[package]] 1069 | name = "time" 1070 | version = "0.3.9" 1071 | source = "registry+https://github.com/rust-lang/crates.io-index" 1072 | checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" 1073 | dependencies = [ 1074 | "itoa", 1075 | "libc", 1076 | "num_threads", 1077 | "time-macros", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "time-macros" 1082 | version = "0.2.4" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" 1085 | 1086 | [[package]] 1087 | name = "tokio" 1088 | version = "1.19.2" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" 1091 | dependencies = [ 1092 | "bytes", 1093 | "libc", 1094 | "memchr", 1095 | "mio", 1096 | "num_cpus", 1097 | "once_cell", 1098 | "parking_lot", 1099 | "pin-project-lite", 1100 | "signal-hook-registry", 1101 | "socket2", 1102 | "tokio-macros", 1103 | "winapi", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "tokio-macros" 1108 | version = "1.8.0" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" 1111 | dependencies = [ 1112 | "proc-macro2", 1113 | "quote", 1114 | "syn", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "tokio-util" 1119 | version = "0.7.3" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" 1122 | dependencies = [ 1123 | "bytes", 1124 | "futures-core", 1125 | "futures-sink", 1126 | "pin-project-lite", 1127 | "tokio", 1128 | "tracing", 1129 | ] 1130 | 1131 | [[package]] 1132 | name = "toml" 1133 | version = "0.5.9" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" 1136 | dependencies = [ 1137 | "serde", 1138 | ] 1139 | 1140 | [[package]] 1141 | name = "tracing" 1142 | version = "0.1.35" 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" 1144 | checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" 1145 | dependencies = [ 1146 | "cfg-if", 1147 | "pin-project-lite", 1148 | "tracing-core", 1149 | ] 1150 | 1151 | [[package]] 1152 | name = "tracing-core" 1153 | version = "0.1.27" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" 1156 | dependencies = [ 1157 | "once_cell", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "ucd-trie" 1162 | version = "0.1.3" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" 1165 | 1166 | [[package]] 1167 | name = "unicode-ident" 1168 | version = "1.0.1" 1169 | source = "registry+https://github.com/rust-lang/crates.io-index" 1170 | checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" 1171 | 1172 | [[package]] 1173 | name = "unicode-width" 1174 | version = "0.1.9" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" 1177 | 1178 | [[package]] 1179 | name = "users" 1180 | version = "0.8.1" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "7fed7d0912567d35f88010c23dbaf865e9da8b5227295e8dc0f2fdd109155ab7" 1183 | dependencies = [ 1184 | "libc", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "uuid" 1189 | version = "1.1.2" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" 1192 | dependencies = [ 1193 | "getrandom", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "vec_map" 1198 | version = "0.8.2" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 1201 | 1202 | [[package]] 1203 | name = "version-compare" 1204 | version = "0.1.0" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" 1207 | 1208 | [[package]] 1209 | name = "version_check" 1210 | version = "0.9.4" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1213 | 1214 | [[package]] 1215 | name = "wasi" 1216 | version = "0.11.0+wasi-snapshot-preview1" 1217 | source = "registry+https://github.com/rust-lang/crates.io-index" 1218 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1219 | 1220 | [[package]] 1221 | name = "winapi" 1222 | version = "0.3.9" 1223 | source = "registry+https://github.com/rust-lang/crates.io-index" 1224 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1225 | dependencies = [ 1226 | "winapi-i686-pc-windows-gnu", 1227 | "winapi-x86_64-pc-windows-gnu", 1228 | ] 1229 | 1230 | [[package]] 1231 | name = "winapi-i686-pc-windows-gnu" 1232 | version = "0.4.0" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1235 | 1236 | [[package]] 1237 | name = "winapi-x86_64-pc-windows-gnu" 1238 | version = "0.4.0" 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" 1240 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1241 | 1242 | [[package]] 1243 | name = "windows-sys" 1244 | version = "0.36.1" 1245 | source = "registry+https://github.com/rust-lang/crates.io-index" 1246 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 1247 | dependencies = [ 1248 | "windows_aarch64_msvc", 1249 | "windows_i686_gnu", 1250 | "windows_i686_msvc", 1251 | "windows_x86_64_gnu", 1252 | "windows_x86_64_msvc", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "windows_aarch64_msvc" 1257 | version = "0.36.1" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 1260 | 1261 | [[package]] 1262 | name = "windows_i686_gnu" 1263 | version = "0.36.1" 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" 1265 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 1266 | 1267 | [[package]] 1268 | name = "windows_i686_msvc" 1269 | version = "0.36.1" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 1272 | 1273 | [[package]] 1274 | name = "windows_x86_64_gnu" 1275 | version = "0.36.1" 1276 | source = "registry+https://github.com/rust-lang/crates.io-index" 1277 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 1278 | 1279 | [[package]] 1280 | name = "windows_x86_64_msvc" 1281 | version = "0.36.1" 1282 | source = "registry+https://github.com/rust-lang/crates.io-index" 1283 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 1284 | --------------------------------------------------------------------------------