diff --git a/src/main.rs b/src/main.rs index 32cc095..aede4bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ use std::time::Duration; use std::ffi::{CStr, CString}; use std::fs::{self, File}; use std::mem; -use std::io::{Write}; +use std::io::{Write, BufReader, BufRead}; use simple_input::input; use tempfile::NamedTempFile; @@ -249,7 +249,7 @@ pub struct BrowserState { pub parsed_host: String, pub parsed_port: usize, pub parsed_selector: String, - pub bookmarks: [[u8; 512]; 20], + pub bookmarks: Vec, pub config: Config, } @@ -266,7 +266,7 @@ impl BrowserState { parsed_host: String::new(), parsed_port: 0, parsed_selector: String::new(), - bookmarks: [[0; 512]; 20], + bookmarks: Vec::new(), config: Config { start_uri: String::from("gopher://gopher.floodgap.com:70"), cmd_text: String::from("less"), @@ -280,198 +280,45 @@ impl BrowserState { } } - unsafe fn parse_config_line(&mut self, mut line: *const libc::c_char) { - let mut token: [libc::c_char; 1024] = [0; 1024]; - let mut bkey: [libc::c_char; 128] = [0; 128]; - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut i: libc::c_int = 0; - let mut j: libc::c_int = 0; - while *line as libc::c_int == ' ' as i32 || *line as libc::c_int == '\t' as i32 { - line = line.offset(1) - } - i = 0 as libc::c_int; - while *line as libc::c_int != 0 - && *line as libc::c_int != ' ' as i32 - && *line as libc::c_int != '\t' as i32 - { - if (i as libc::c_ulong) - < (mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong) - .wrapping_sub(1 as libc::c_int as libc::c_ulong) - { - let fresh0 = i; - i = i + 1; - token[fresh0 as usize] = *line - } - line = line.offset(1) - } - token[i as usize] = 0 as libc::c_int as libc::c_char; - if strcmp( - token.as_mut_ptr(), - b"start_uri\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.start_uri.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"cmd_text\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.cmd_text.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"cmd_browser\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.cmd_browser.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"cmd_image\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.cmd_image.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"cmd_player\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.cmd_player.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"color_prompt\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.color_prompt.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"color_selector\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.color_selector.clone()).unwrap().into_raw(); - } else if strcmp( - token.as_mut_ptr(), - b"verbose\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - value = CString::new(self.config.verbose.clone()).unwrap().into_raw(); - } else { - j = 0 as libc::c_int; - while j < 20 as libc::c_int { - snprintf( - bkey.as_mut_ptr(), - mem::size_of::<[libc::c_char; 128]>() as libc::c_ulong, - b"bookmark%d\x00" as *const u8 as *const libc::c_char, - j + 1 as libc::c_int, - ); - if strcmp(token.as_mut_ptr(), bkey.as_mut_ptr()) == 0 { - value = CString::new(self.bookmarks[j as usize]).unwrap().into_raw(); - break; - } else { - j += 1 - } - } - if value.is_null() { - return; - } - } - while *line as libc::c_int == ' ' as i32 || *line as libc::c_int == '\t' as i32 { - line = line.offset(1) - } - i = 0 as libc::c_int; - while *line != 0 { - if i < 512 as libc::c_int - 1 as libc::c_int { - let fresh1 = i; - i = i + 1; - *value.offset(fresh1 as isize) = *line - } - line = line.offset(1) - } - i -= 1; - while i > 0 as libc::c_int - && (*value.offset(i as isize) as libc::c_int == ' ' as i32 - || *value.offset(i as isize) as libc::c_int == '\t' as i32) - { - i -= 1 + unsafe fn parse_config_line(&mut self, line: &str) { + let trimmed_line = line.trim_start(); + + let words = trimmed_line.split_whitespace().take(2).collect::>(); + match words[0] { + "start_uri" => self.config.start_uri = words[1].to_string(), + "cmd_text" => self.config.cmd_text = words[1].to_string(), + "cmd_browser" => self.config.cmd_browser = words[1].to_string(), + "cmd_image" => self.config.cmd_image = words[1].to_string(), + "cmd_player" => self.config.cmd_player = words[1].to_string(), + "color_prompt" => self.config.color_prompt = words[1].to_string(), + "color_selector" => self.config.color_selector = words[1].to_string(), + "verbose" => self.config.verbose = words[1].to_string(), + x if x.starts_with("bookmark") => self.bookmarks.push(words[1].to_string()), + x => { + eprintln!("invalid key in config: {}", x); + exit(1) + }, } - i += 1; - *value.offset(i as isize) = 0 as libc::c_int as libc::c_char; } - pub unsafe fn load_config(&mut self, mut filename: *const libc::c_char) { - let mut fp: *mut FILE = 0 as *mut FILE; - let mut ch: libc::c_int = 0; - let mut i: libc::c_int = 0; - let mut line: [libc::c_char; 1024] = [0; 1024]; - fp = fopen(filename, b"r\x00" as *const u8 as *const libc::c_char); - if fp.is_null() { - return; - } - memset( - line.as_mut_ptr() as *mut libc::c_void, - 0 as libc::c_int, - mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong, - ); - i = 0 as libc::c_int; - ch = fgetc(fp); - loop { - match ch { - 35 => - while ch != '\n' as i32 && ch != -(1 as libc::c_int) { - ch = fgetc(fp) - }, - -1 => { - self.parse_config_line(line.as_mut_ptr()); - fclose(fp); - return; - } - 13 => ch = fgetc(fp), - 10 => { - self.parse_config_line(line.as_mut_ptr()); - memset( - line.as_mut_ptr() as *mut libc::c_void, - 0 as libc::c_int, - mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong, - ); - i = 0 as libc::c_int; - ch = fgetc(fp) - } - _ => { - if (i as libc::c_ulong) - < (mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong) - .wrapping_sub(1 as libc::c_int as libc::c_ulong) - { - let fresh2 = i; - i = i + 1; - line[fresh2 as usize] = ch as libc::c_char - } - ch = fgetc(fp) - } + pub unsafe fn load_config>(&mut self, filename: P) { + let mut file = match File::open(filename) { + Ok(f) => BufReader::new(f), + Err(_) => { + return; } - } + }; + file.lines().filter_map(|x| x.ok()).filter(|x| !x.starts_with('#')).for_each(|line| { + self.parse_config_line(&line) + }) } pub unsafe fn init_config(&mut self) { - let mut filename: [libc::c_char; 1024] = [0; 1024]; - let mut home: *const libc::c_char = 0 as *const libc::c_char; - let mut i: libc::c_int = 0; - /* copy defaults */ - i = 0 as libc::c_int; - while i < 20 as libc::c_int { - self.bookmarks[i as usize][0 as libc::c_int as usize] = 0; - i += 1 - } /* read configs */ - self.load_config(b"/etc/cgorc\x00" as *const u8 as *const libc::c_char); /* ignore incomplete selectors */ - home = getenv(b"HOME\x00" as *const u8 as *const libc::c_char); /* not needed for history...just clear them */ - if !home.is_null() { - snprintf( - filename.as_mut_ptr(), - mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong, - b"%s%s\x00" as *const u8 as *const libc::c_char, - home, - b"/.cgorc\x00" as *const u8 as *const libc::c_char, - ); - self.load_config(filename.as_mut_ptr()); - }; + self.load_config("/etc/cgorc"); /* ignore incomplete selectors */ + if let Some(dir) = env::home_dir() { + self.load_config(dir.join(".cgorc")); + } } pub unsafe fn download_file( @@ -958,44 +805,20 @@ impl BrowserState { if key.is_none() { println!("(bookmarks)"); i = 0; - while i < 20 { - if self.bookmarks[i as usize][0] != 0 { - make_key_str(i, &mut a, &mut b, &mut c); - println!( - "{}{}{} {}", - a, - b, - c, - CString::new( - self.bookmarks[i as usize] - .iter() - .take_while(|x| **x != 0) - .cloned() - .collect::>() - ) - .unwrap() - .into_string() - .unwrap() - ); - } - i += 1 + for bookmark in &self.bookmarks { + make_key_str(i, &mut a, &mut b, &mut c); + println!( + "{}{}{} {}", + a, + b, + c, + bookmark + ); } } else if let Some(key) = key { - i = 0; - while i < 20 { - if self.bookmarks[i][0] != 0 && i == key { - if self.parse_uri( - CString::new( - self.bookmarks[i] - .iter() - .take_while(|x| **x != 0) - .cloned() - .collect::>(), - ) - .unwrap() - .into_string() - .unwrap(), - ) { + for (i, bookmark) in self.bookmarks.clone().iter().enumerate() { + if i == key { + if self.parse_uri(bookmark) { self.view_directory( &self.parsed_host.clone(), self.parsed_port.clone(), @@ -1005,21 +828,11 @@ impl BrowserState { } else { println!( "invalid gopher URI: {}", - CString::new( - self.bookmarks[i] - .iter() - .take_while(|x| **x != 0) - .cloned() - .collect::>() - ) - .unwrap() - .into_string() - .unwrap() + bookmark, ); } return; } - i += 1 } }; } @@ -1133,7 +946,7 @@ impl BrowserState { } /* function prototypes */ - pub unsafe fn parse_uri(&mut self, mut uri: String) -> bool { + pub unsafe fn parse_uri(&mut self, uri: &str) -> bool { let mut tmp: &str = &uri[..]; /* strip gopher:// */ if uri.starts_with("gopher://") { @@ -1205,7 +1018,7 @@ impl BrowserState { i += 1 } /* parse uri */ - if !self.parse_uri(uri) { + if !self.parse_uri(&uri) { banner(false); eprintln!("invalid gopher URI: {}", argv[i],); exit(1); @@ -1285,7 +1098,7 @@ impl BrowserState { }, 71 => { if self.parse_uri( - CString::from_raw( + &CString::from_raw( &mut *line.as_mut_ptr().offset(1 as libc::c_int as isize) as *mut u8 as *mut i8, )