network-manager 0.11.0

Rust NetworkManager bindings
Documentation
#[macro_use]
extern crate error_chain;

extern crate network_manager;

use std::env;
use std::process;
use std::io::Write;

use network_manager::{AccessPoint, AccessPointCredentials, Device, DeviceType, NetworkManager};

mod errors {
    use network_manager;

    error_chain! {
        links {
            NetworkManager(network_manager::errors::Error, network_manager::errors::ErrorKind);
        }

        errors {
            Runtime(info: String) {
                description("Runtime error")
                display("{}", info)
            }
        }
    }
}

use errors::*;

fn main() {
    if let Err(ref e) = run() {
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "{}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "  caused by: {}", e).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    let args: Vec<String> = env::args().collect();

    if args.len() != 3 {
        println!("USAGE: create SSID PASSWORD");
        process::exit(1);
    }

    let manager = NetworkManager::new();

    let device = find_device(&manager)?;

    let wifi_device = device.as_wifi_device().unwrap();

    let access_points = wifi_device.get_access_points()?;

    let ap_index = find_access_point(&access_points, &args[1] as &str)?;

    let credentials = AccessPointCredentials::Wpa {
        passphrase: args[2].clone(),
    };

    wifi_device.connect(&access_points[ap_index], &credentials)?;

    Ok(())
}

fn find_device(manager: &NetworkManager) -> Result<Device> {
    let devices = manager.get_devices()?;

    let index = devices
        .iter()
        .position(|d| *d.device_type() == DeviceType::WiFi);

    if let Some(index) = index {
        Ok(devices[index].clone())
    } else {
        bail!(ErrorKind::Runtime("Cannot find a WiFi device".into()))
    }
}

fn find_access_point(access_points: &[AccessPoint], ssid: &str) -> Result<usize> {
    if let Some(index) = access_points.iter().position(|ap| same_ssid(ap, ssid)) {
        Ok(index)
    } else {
        bail!(ErrorKind::Runtime("Access point not found".into()))
    }
}

fn same_ssid(ap: &AccessPoint, ssid: &str) -> bool {
    if let Ok(ap_ssid) = ap.ssid().as_str() {
        ap_ssid == ssid
    } else {
        false
    }
}