1
+ extern crate clap;
2
+ extern crate libc;
1
3
extern crate ref_slice;
2
4
5
+ #[ macro_use]
6
+ extern crate error_chain;
7
+
8
+ use std:: ffi:: CString ;
3
9
use std:: fs:: File ;
4
10
use std:: io:: { Read , Write } ;
11
+ use std:: os:: unix:: ffi:: OsStringExt ;
5
12
use std:: path:: PathBuf ;
6
- use std:: process:: Command ;
7
13
use std:: { env, fs, io, process} ;
8
14
15
+ use clap:: { App , Arg } ;
16
+ use ref_slice:: ref_slice_mut;
17
+
18
+ use errors:: * ;
19
+
20
+ mod errors {
21
+ error_chain ! ( ) ;
22
+ }
23
+
9
24
fn main ( ) {
10
- let pipe = & PathBuf :: from ( env:: args_os ( )
11
- . skip ( 1 )
12
- . next ( )
13
- . unwrap_or_else ( || exit ( "expected one argument: the path to the named pipe" ) ) ) ;
25
+ if let Err ( e) = run ( ) {
26
+ let stderr = io:: stderr ( ) ;
27
+ let mut stderr = stderr. lock ( ) ;
28
+
29
+ writeln ! ( stderr, "{}" , e) . ok ( ) ;
30
+
31
+ for e in e. iter ( ) . skip ( 1 ) {
32
+ writeln ! ( stderr, "caused by: {}" , e) . ok ( ) ;
33
+ }
34
+
35
+ if show_backtrace ( ) {
36
+ if let Some ( backtrace) = e. backtrace ( ) {
37
+ writeln ! ( stderr, "backtrace:" ) . ok ( ) ;
38
+ writeln ! ( stderr, "{:?}" , backtrace) . ok ( ) ;
39
+ }
40
+ }
41
+
42
+ process:: exit ( 1 )
43
+ }
44
+ }
45
+
46
+ fn run ( ) -> Result < ( ) > {
47
+ let matches = App :: new ( "itmdump" )
48
+ . version ( env ! ( "CARGO_PKG_VERSION" ) )
49
+ . arg ( Arg :: with_name ( "PATH" ) . help ( "Named pipe to use" ) . required ( true ) )
50
+ . get_matches ( ) ;
51
+
52
+ let pipe = PathBuf :: from ( matches. value_of ( "PATH" ) . unwrap ( ) ) ;
53
+ let pipe_ = pipe. display ( ) ;
14
54
15
55
if pipe. exists ( ) {
16
- fs:: remove_file ( pipe)
17
- . unwrap_or_else ( |_| exit ( & format ! ( "couldn't remove {}" , pipe . display ( ) ) ) ) ;
56
+ try! ( fs:: remove_file ( & pipe)
57
+ . chain_err ( || format ! ( "couldn't remove {}" , pipe_ ) ) ) ;
18
58
}
19
59
20
- let output = Command :: new ( "mkfifo" ) . arg ( pipe) . output ( ) . unwrap_or_else ( |_| {
21
- exit ( "`mkfifo` not found" ) ;
22
- } ) ;
60
+ let cpipe = try!( CString :: new ( pipe. clone ( ) . into_os_string ( ) . into_vec ( ) )
61
+ . chain_err ( || format ! ( "error converting {} to a C string" , pipe_) ) ) ;
23
62
24
- if !output. status . success ( ) {
25
- exit ( & String :: from_utf8_lossy ( & output. stderr ) )
63
+ match unsafe { libc:: mkfifo ( cpipe. as_ptr ( ) , 0o644 ) } {
64
+ 0 => { }
65
+ e => {
66
+ try!( Err ( io:: Error :: from_raw_os_error ( e) ) . chain_err ( || {
67
+ format ! ( "couldn't create a named pipe in {}" , pipe_)
68
+ } ) )
69
+ }
26
70
}
27
71
28
- let mut stream = File :: open ( pipe)
29
- . unwrap_or_else ( |_| exit ( & format ! ( "couldn't open {}" , pipe . display ( ) ) ) ) ;
72
+ let mut stream = try! ( File :: open ( & pipe)
73
+ . chain_err ( || format ! ( "couldn't open {}" , pipe_ ) ) ) ;
30
74
31
75
let mut header = 0 ;
32
76
33
77
let ( stdout, stderr) = ( io:: stdout ( ) , io:: stderr ( ) ) ;
34
78
let ( mut stdout, mut stderr) = ( stdout. lock ( ) , stderr. lock ( ) ) ;
35
79
loop {
36
80
if let Err ( e) = ( || {
37
- try!( stream. read_exact ( ref_slice :: ref_slice_mut ( & mut header) ) ) ;
81
+ try!( stream. read_exact ( ref_slice_mut ( & mut header) ) ) ;
38
82
let port = header >> 3 ;
39
83
40
84
// Ignore all the packets that don't come from the stimulus port 0
@@ -45,7 +89,7 @@ fn main() {
45
89
match header & 0b111 {
46
90
0b01 => {
47
91
let mut payload = 0 ;
48
- try!( stream. read_exact ( ref_slice :: ref_slice_mut ( & mut payload) ) ) ;
92
+ try!( stream. read_exact ( ref_slice_mut ( & mut payload) ) ) ;
49
93
stdout. write_all ( & [ payload] )
50
94
}
51
95
0b10 => {
@@ -69,8 +113,6 @@ fn main() {
69
113
}
70
114
}
71
115
72
- fn exit ( msg : & str ) -> ! {
73
- let stderr = io:: stderr ( ) ;
74
- writeln ! ( stderr. lock( ) , "{}" , msg) . ok ( ) ;
75
- process:: exit ( 1 )
116
+ fn show_backtrace ( ) -> bool {
117
+ env:: var ( "RUST_BACKTRACE" ) . as_ref ( ) . map ( |s| & s[ ..] ) == Ok ( "1" )
76
118
}
0 commit comments