From 88d3f71dc79ebd5fc6b21999240935930da84273 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 26 Oct 2018 00:47:26 +0200 Subject: Add a `--license` command line argument Add a new argument that allows users to pass in the path to a license file. Doing so should get picked up by the Objective-C code which will copy and validate the license. In order for the Objective-C code to pick up the path string, we add a `license` field to the `Config.Args` struct. The new `license` field is a `*mut c_char`, which means we can't derive Default any more and need to implement a custom `Default` impl for `Args`. Additionally, 'getopts' gives us a Rust string (of course), which needs to be converted into a raw `CString` before we can stick it in the `license` field in `Args`. I previously wrote `dkeprintln` to be able to print an error here at the conversion point between `CString` and raw C string. Since we used `CString#into_raw()`, we need to call `from_raw()` on the pointer to free it, otherwise we end up with a memory leak. This necessitated adding some additional code to `config_free()` to free the `license` field if non-null. In order to access `config.args.license` from within `config_free()`, I also needed to make the `args` and `license` struct fields public, since the free function is in a different module. Instead of making only those two fields public, I decided to make them all public, as all the fields are technically accessible from C code, and are needed by that C code. Finally, move the module declaration of `prefix_println` to the top of the module list instead of listing it alphabetically, because otherwise any modules declared before it (like `config`) don't get access to its macro. Also add a `#[macro_use]` attribute to the module declaration because we do want to export its macro. (https://stackoverflow.com/questions/26731243/how-do-i-use-a-macro-across-module-files#comment78329437_31749071) --- src/cocoa_bridge.rs | 5 ++++- src/config.rs | 37 +++++++++++++++++++++++++++++++------ src/lib.rs | 4 +++- 3 files changed, 38 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cocoa_bridge.rs b/src/cocoa_bridge.rs index 7b707de..cd1dafa 100644 --- a/src/cocoa_bridge.rs +++ b/src/cocoa_bridge.rs @@ -346,7 +346,10 @@ pub extern "C" fn config_get() -> *mut Config { #[no_mangle] pub extern "C" fn config_free(ptr: *mut Config) { if ptr.is_null() { return } - unsafe { Box::from_raw(ptr); } + let config = unsafe { Box::from_raw(ptr) }; + + if config.args.license.is_null() { return } + unsafe { CString::from_raw(config.args.license); } } diff --git a/src/config.rs b/src/config.rs index feaf578..b4cab10 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,18 +1,32 @@ +use std::ffi::CString; use std::fs; +use std::ptr; +use libc::c_char; use getopts::Options; use toml; use xdg; use errors::*; +use prefix_println; type Milliseconds = u16; #[repr(C)] -#[derive(Default)] -struct Args { - reload: bool, - daemon: bool, +pub struct Args { + pub reload: bool, + pub daemon: bool, + pub license: *mut c_char, +} + +impl Default for Args { + fn default() -> Self { + Args { + reload: false, + daemon: false, + license: ptr::null_mut(), + } + } } #[repr(C)] @@ -20,8 +34,8 @@ struct Args { #[serde(default)] pub struct Config { #[serde(skip)] - args: Args, - timeout: Milliseconds, + pub args: Args, + pub timeout: Milliseconds, } impl Default for Config { @@ -43,6 +57,12 @@ pub fn parse_args<'a>(args: &[String], config: &'a mut Config) -> &'a mut Config opts.optflag("d", "daemon", "run the daemon in the current shell"); opts.optflag("r", "reload-mappings", "reload the mappings file"); + opts.optopt( + "", + "license", + "register the software using a license plist file", + "FILE" + ); opts.optflag("h", "help", "print this help menu"); let matches = match opts.parse(&args[1..]) { @@ -59,6 +79,11 @@ pub fn parse_args<'a>(args: &[String], config: &'a mut Config) -> &'a mut Config config.args.reload = true; } else if matches.opt_present("d") { config.args.daemon = true; + } else if let Some(license_path) = matches.opt_str("license") { + match CString::new(license_path) { + Ok(str) => config.args.license = str.into_raw(), + Err(e) => dkeprintln!("{}", e), + } } else { print_usage(opts); } diff --git a/src/lib.rs b/src/lib.rs index 6a08e4b..1e0daa6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,13 +31,15 @@ extern crate stderrlog; extern crate toml; extern crate xdg; +#[macro_use] +mod prefix_println; + mod autopilot_internal; mod cocoa_bridge; mod config; mod errors; mod key_code; mod parser; -mod prefix_println; mod trial; use parser::{Action, HeadphoneButton, MapAction, MapGroup, MapKind}; -- cgit v1.2.3