aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 08cd67e47e4674dfc2373bb63186f67e805bdfbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

// XXX: re-enable these warnings
#![allow(unused_imports, unused_variables, unused_mut)]

#[macro_use] extern crate log;
extern crate env_logger;
extern crate getopts;
extern crate udt;
extern crate sodiumoxide;
extern crate rustc_serialize;

mod client;
mod server;
mod common;
mod udt_extras;
mod crypto;
use std::io::Write;
use std::str;
use std::env;
use std::process::exit;
use getopts::Options;
use udt::{UdtSocket};

fn usage(opts: Options) {
    let brief = "usage:\tucp [-h] [-v] [[user@]host1:]srcfile [[user@]host2:]destfile";
    print!("{}", opts.usage(&brief));
}

fn main() {

    let args: Vec<String> = env::args().collect();
    sodiumoxide::init();

    // First check for "hidden" server and client modes
    if args.len() > 1 && args[1] == "server" {
        server::main_server();
        return;
    } else if args.len() > 1 && args[1] == "client" {
        client::main_client();
        return;
    }

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("v", "verbose", "more debugging messages");
    opts.optflag("r", "recursive", "whether to recursively transfer files (directory)");
    opts.optflag("", "no-crypto", "sends data in the clear (no crypto or verification)");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { println!("{}", f.to_string()); usage(opts); exit(-1); }
    };

    let verbose: bool = matches.opt_present("v");
    let recursive: bool = matches.opt_present("r");
    let no_crypto: bool = matches.opt_present("no-crypto");

    if matches.opt_present("h") {
        usage(opts);
        return;
    }

    if matches.free.len() != 2 {
        println!("Expected a single source and single destination");
        println!("");
        usage(opts);
        return;
    }

    let srcfile = matches.free[0].clone();
    let destfile = matches.free[1].clone();

    for fname in vec![&srcfile, &destfile] {
        if fname.match_indices(":").count() > 2 {
            println!("Invalid host/file identifier: {}", fname);
            exit(-1);
        }
    }

    let mut ret: Result<(), String>;
    match (srcfile.contains(":"), destfile.contains(":")) {
        (true, true)    => { println!("Can't have src and dest both be remote!"); exit(-1); },
        (false, false)  => { println!("One of src or dest should be remote!"); exit(-1); },
        (true , false)  => {
            let is_recv = true;
            let local_file = &destfile;
            let spl: Vec<&str> = srcfile.split(":").collect();
            let host = spl[0];
            let remote_file = spl[1];
            ret = client::run_client(host, local_file, remote_file, recursive, is_recv, no_crypto, verbose);
            },
        (false, true)   => {
            let is_recv = false;
            let local_file = &srcfile;
            let spl: Vec<&str> = destfile.split(":").collect();
            let host = spl[0];
            let remote_file = spl[1];
            ret = client::run_client(host, local_file, remote_file, recursive, is_recv, no_crypto, verbose);
            },
    }

    match ret {
        Ok(_) => { exit(0); },
        Err(msg) => {
            writeln!(&mut ::std::io::stderr(), "{}", msg).unwrap();
            exit(-1);
        }
    }
}