]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! ncurses-compatible database discovery | |
12 | //! | |
13 | //! Does not support hashed database, only filesystem! | |
14 | ||
85aaf69f | 15 | use std::env; |
c34b1796 AL |
16 | use std::fs::File; |
17 | use std::io::prelude::*; | |
18 | use std::path::PathBuf; | |
1a4d82fc JJ |
19 | |
20 | /// Return path to database entry for `term` | |
c34b1796 AL |
21 | #[allow(deprecated)] |
22 | pub fn get_dbpath_for_term(term: &str) -> Option<Box<PathBuf>> { | |
9346a6ac | 23 | if term.is_empty() { |
1a4d82fc JJ |
24 | return None; |
25 | } | |
26 | ||
85aaf69f | 27 | let homedir = env::home_dir(); |
1a4d82fc JJ |
28 | |
29 | let mut dirs_to_search = Vec::new(); | |
30 | let first_char = term.char_at(0); | |
31 | ||
32 | // Find search directory | |
c34b1796 AL |
33 | match env::var_os("TERMINFO") { |
34 | Some(dir) => dirs_to_search.push(PathBuf::from(dir)), | |
35 | None => { | |
1a4d82fc JJ |
36 | if homedir.is_some() { |
37 | // ncurses compatibility; | |
38 | dirs_to_search.push(homedir.unwrap().join(".terminfo")) | |
39 | } | |
85aaf69f SL |
40 | match env::var("TERMINFO_DIRS") { |
41 | Ok(dirs) => for i in dirs.split(':') { | |
1a4d82fc | 42 | if i == "" { |
c34b1796 | 43 | dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); |
1a4d82fc | 44 | } else { |
c34b1796 | 45 | dirs_to_search.push(PathBuf::from(i)); |
1a4d82fc JJ |
46 | } |
47 | }, | |
48 | // Found nothing in TERMINFO_DIRS, use the default paths: | |
49 | // According to /etc/terminfo/README, after looking at | |
50 | // ~/.terminfo, ncurses will search /etc/terminfo, then | |
51 | // /lib/terminfo, and eventually /usr/share/terminfo. | |
85aaf69f | 52 | Err(..) => { |
c34b1796 AL |
53 | dirs_to_search.push(PathBuf::from("/etc/terminfo")); |
54 | dirs_to_search.push(PathBuf::from("/lib/terminfo")); | |
55 | dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); | |
1a4d82fc JJ |
56 | } |
57 | } | |
58 | } | |
59 | }; | |
60 | ||
61 | // Look for the terminal in all of the search directories | |
85aaf69f | 62 | for p in &dirs_to_search { |
1a4d82fc JJ |
63 | if p.exists() { |
64 | let f = first_char.to_string(); | |
c34b1796 | 65 | let newp = p.join(&f).join(term); |
1a4d82fc JJ |
66 | if newp.exists() { |
67 | return Some(box newp); | |
68 | } | |
69 | // on some installations the dir is named after the hex of the char (e.g. OS X) | |
c34b1796 AL |
70 | let f = format!("{:x}", first_char as usize); |
71 | let newp = p.join(&f).join(term); | |
1a4d82fc JJ |
72 | if newp.exists() { |
73 | return Some(box newp); | |
74 | } | |
75 | } | |
76 | } | |
77 | None | |
78 | } | |
79 | ||
80 | /// Return open file for `term` | |
81 | pub fn open(term: &str) -> Result<File, String> { | |
82 | match get_dbpath_for_term(term) { | |
83 | Some(x) => { | |
84 | match File::open(&*x) { | |
85 | Ok(file) => Ok(file), | |
86 | Err(e) => Err(format!("error opening file: {:?}", e)), | |
87 | } | |
88 | } | |
89 | None => { | |
90 | Err(format!("could not find terminfo entry for {:?}", term)) | |
91 | } | |
92 | } | |
93 | } | |
94 | ||
95 | #[test] | |
96 | #[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")] | |
97 | fn test_get_dbpath_for_term() { | |
98 | // woefully inadequate test coverage | |
99 | // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's) | |
c34b1796 | 100 | use std::env; |
1a4d82fc JJ |
101 | // FIXME (#9639): This needs to handle non-utf8 paths |
102 | fn x(t: &str) -> String { | |
103 | let p = get_dbpath_for_term(t).expect("no terminfo entry found"); | |
c34b1796 | 104 | p.to_str().unwrap().to_string() |
1a4d82fc JJ |
105 | }; |
106 | assert!(x("screen") == "/usr/share/terminfo/s/screen"); | |
107 | assert!(get_dbpath_for_term("") == None); | |
c34b1796 | 108 | env::set_var("TERMINFO_DIRS", ":"); |
1a4d82fc | 109 | assert!(x("screen") == "/usr/share/terminfo/s/screen"); |
c34b1796 | 110 | env::remove_var("TERMINFO_DIRS"); |
1a4d82fc JJ |
111 | } |
112 | ||
113 | #[test] | |
114 | #[ignore(reason = "see test_get_dbpath_for_term")] | |
115 | fn test_open() { | |
116 | open("screen").unwrap(); | |
117 | let t = open("nonexistent terminal that hopefully does not exist"); | |
118 | assert!(t.is_err()); | |
119 | } |