|
|
|
@ -28,9 +28,6 @@ use simple_input::input;
|
|
|
|
|
use tempfile::NamedTempFile;
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
pub type _IO_wide_data;
|
|
|
|
|
pub type _IO_codecvt;
|
|
|
|
|
pub type _IO_marker;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn waitpid(
|
|
|
|
|
__pid: __pid_t,
|
|
|
|
@ -57,8 +54,6 @@ extern "C" {
|
|
|
|
|
__pai: *mut *mut addrinfo,
|
|
|
|
|
) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn freeaddrinfo(__ai: *mut addrinfo);
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn open(__file: *const libc::c_char, __oflag: libc::c_int, _: ...) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn close(__fd: libc::c_int) -> libc::c_int;
|
|
|
|
@ -80,18 +75,8 @@ extern "C" {
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn fork() -> __pid_t;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn unlink(__name: *const libc::c_char) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn __errno_location() -> *mut libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
static mut stderr: *mut FILE;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn fclose(__stream: *mut FILE) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn fopen(_: *const libc::c_char, _: *const libc::c_char) -> *mut FILE;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn fprintf(_: *mut FILE, _: *const libc::c_char, _: ...) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn snprintf(
|
|
|
|
@ -101,20 +86,10 @@ extern "C" {
|
|
|
|
|
_: ...
|
|
|
|
|
) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn fgetc(__stream: *mut FILE) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn fputs(__s: *const libc::c_char, __stream: *mut FILE) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn puts(__s: *const libc::c_char) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn free(__ptr: *mut libc::c_void);
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn getenv(__name: *const libc::c_char) -> *mut libc::c_char;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn mkstemp(__template: *mut libc::c_char) -> libc::c_int;
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
fn memset(
|
|
|
|
|
_: *mut libc::c_void,
|
|
|
|
|
_: libc::c_int,
|
|
|
|
@ -179,41 +154,6 @@ pub struct addrinfo {
|
|
|
|
|
pub ai_canonname: *mut libc::c_char,
|
|
|
|
|
pub ai_next: *mut addrinfo,
|
|
|
|
|
}
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
pub struct _IO_FILE {
|
|
|
|
|
pub _flags: libc::c_int,
|
|
|
|
|
pub _IO_read_ptr: *mut libc::c_char,
|
|
|
|
|
pub _IO_read_end: *mut libc::c_char,
|
|
|
|
|
pub _IO_read_base: *mut libc::c_char,
|
|
|
|
|
pub _IO_write_base: *mut libc::c_char,
|
|
|
|
|
pub _IO_write_ptr: *mut libc::c_char,
|
|
|
|
|
pub _IO_write_end: *mut libc::c_char,
|
|
|
|
|
pub _IO_buf_base: *mut libc::c_char,
|
|
|
|
|
pub _IO_buf_end: *mut libc::c_char,
|
|
|
|
|
pub _IO_save_base: *mut libc::c_char,
|
|
|
|
|
pub _IO_backup_base: *mut libc::c_char,
|
|
|
|
|
pub _IO_save_end: *mut libc::c_char,
|
|
|
|
|
pub _markers: *mut _IO_marker,
|
|
|
|
|
pub _chain: *mut _IO_FILE,
|
|
|
|
|
pub _fileno: libc::c_int,
|
|
|
|
|
pub _flags2: libc::c_int,
|
|
|
|
|
pub _old_offset: __off_t,
|
|
|
|
|
pub _cur_column: libc::c_ushort,
|
|
|
|
|
pub _vtable_offset: libc::c_schar,
|
|
|
|
|
pub _shortbuf: [libc::c_char; 1],
|
|
|
|
|
pub _lock: *mut libc::c_void,
|
|
|
|
|
pub _offset: __off64_t,
|
|
|
|
|
pub _codecvt: *mut _IO_codecvt,
|
|
|
|
|
pub _wide_data: *mut _IO_wide_data,
|
|
|
|
|
pub _freeres_list: *mut _IO_FILE,
|
|
|
|
|
pub _freeres_buf: *mut libc::c_void,
|
|
|
|
|
pub __pad5: size_t,
|
|
|
|
|
pub _mode: libc::c_int,
|
|
|
|
|
pub _unused2: [libc::c_char; 20],
|
|
|
|
|
}
|
|
|
|
|
pub type _IO_lock_t = ();
|
|
|
|
|
pub type FILE = _IO_FILE;
|
|
|
|
|
|
|
|
|
|
/* structs */
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
@ -234,7 +174,7 @@ pub struct Config {
|
|
|
|
|
pub cmd_player: String,
|
|
|
|
|
pub color_prompt: String,
|
|
|
|
|
pub color_selector: String,
|
|
|
|
|
pub verbose: String,
|
|
|
|
|
pub verbose: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
@ -275,7 +215,7 @@ impl BrowserState {
|
|
|
|
|
cmd_player: String::from("mplayer"),
|
|
|
|
|
color_prompt: String::from("1;34"),
|
|
|
|
|
color_selector: String::from("1;32"),
|
|
|
|
|
verbose: String::from("true"),
|
|
|
|
|
verbose: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -292,7 +232,7 @@ impl BrowserState {
|
|
|
|
|
"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(),
|
|
|
|
|
"verbose" => self.config.verbose = words[1].parse().unwrap_or_default(),
|
|
|
|
|
x if x.starts_with("bookmark") => self.bookmarks.push(words[1].to_string()),
|
|
|
|
|
x => {
|
|
|
|
|
eprintln!("invalid key in config: {}", x);
|
|
|
|
@ -332,9 +272,7 @@ impl BrowserState {
|
|
|
|
|
let mut len: usize = 0;
|
|
|
|
|
let mut total: usize = 0;
|
|
|
|
|
let mut buffer: [u8; 4096] = [0; 4096];
|
|
|
|
|
if check_option_true(
|
|
|
|
|
CString::new(self.config.verbose.clone()).unwrap().into_raw(),
|
|
|
|
|
) != 0
|
|
|
|
|
if self.config.verbose
|
|
|
|
|
{
|
|
|
|
|
println!("downloading [{}]...", selector);
|
|
|
|
|
}
|
|
|
|
@ -354,17 +292,13 @@ impl BrowserState {
|
|
|
|
|
}
|
|
|
|
|
file.write(&buffer[..len]).expect("failed to write to file");
|
|
|
|
|
total += len;
|
|
|
|
|
if check_option_true(
|
|
|
|
|
CString::new(self.config.verbose.clone()).unwrap().into_raw(),
|
|
|
|
|
) != 0
|
|
|
|
|
if self.config.verbose
|
|
|
|
|
{
|
|
|
|
|
println!("downloading [{}] ({} kb)...", selector, total / 1024);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
close(srvfd);
|
|
|
|
|
if check_option_true(
|
|
|
|
|
CString::new(self.config.verbose.clone()).unwrap().into_raw(),
|
|
|
|
|
) != 0
|
|
|
|
|
if self.config.verbose
|
|
|
|
|
{
|
|
|
|
|
println!("downloading [{}] complete", selector);
|
|
|
|
|
}
|
|
|
|
@ -394,7 +328,7 @@ impl BrowserState {
|
|
|
|
|
|
|
|
|
|
pub unsafe fn add_link(
|
|
|
|
|
&mut self,
|
|
|
|
|
mut which: libc::c_char,
|
|
|
|
|
mut which: char,
|
|
|
|
|
mut name: String,
|
|
|
|
|
mut host: String,
|
|
|
|
|
mut port: usize,
|
|
|
|
@ -450,58 +384,38 @@ impl BrowserState {
|
|
|
|
|
self.history = Some(Box::new(link));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub unsafe fn handle_directory_line(&mut self, mut line: *mut libc::c_char) {
|
|
|
|
|
let mut i: libc::c_int = 0;
|
|
|
|
|
let mut lp: *mut u8 = 0 as *mut u8;
|
|
|
|
|
let mut last: *mut u8 = 0 as *mut u8;
|
|
|
|
|
let mut fields: [*mut u8; 4] = [0 as *mut u8; 4];
|
|
|
|
|
/* tokenize */
|
|
|
|
|
i = 0 as libc::c_int;
|
|
|
|
|
last = &mut *line.offset(1 as libc::c_int as isize) as *mut i8 as *mut u8;
|
|
|
|
|
lp = last;
|
|
|
|
|
i = 0 as libc::c_int;
|
|
|
|
|
while i < 4 as libc::c_int {
|
|
|
|
|
if *lp as libc::c_int == '\t' as i32 || *lp as libc::c_int == '\u{0}' as i32 {
|
|
|
|
|
fields[i as usize] = last;
|
|
|
|
|
last = lp.offset(1 as libc::c_int as isize);
|
|
|
|
|
if *lp as libc::c_int == '\u{0}' as i32 {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*lp = '\0' as u8;
|
|
|
|
|
i += 1
|
|
|
|
|
}
|
|
|
|
|
lp = lp.offset(1)
|
|
|
|
|
}
|
|
|
|
|
pub unsafe fn handle_directory_line(&mut self, line: &str) {
|
|
|
|
|
let fields = {
|
|
|
|
|
let mut v = line[1..].split('\t').collect::<Vec<_>>();
|
|
|
|
|
v.retain(|x| !x.is_empty());
|
|
|
|
|
v
|
|
|
|
|
};
|
|
|
|
|
/* determine listing type */
|
|
|
|
|
match *line.offset(0 as libc::c_int as isize) as libc::c_int {
|
|
|
|
|
105 | 51 => {
|
|
|
|
|
printf(b" %s\n\x00" as *const u8 as *const libc::c_char, fields[0]);
|
|
|
|
|
}
|
|
|
|
|
46 => {
|
|
|
|
|
/* some gopher servers use this */
|
|
|
|
|
puts(b"\x00" as *const u8 as *const libc::c_char);
|
|
|
|
|
}
|
|
|
|
|
48 | 49 | 53 | 55 | 56 | 57 | 103 | 73 | 112 | 104 | 115 => {
|
|
|
|
|
match line.chars().next() {
|
|
|
|
|
Some('i') | Some('3') => println!(" {}", fields[0]),
|
|
|
|
|
Some('.') => println!("\0"), // some gopher servers use this
|
|
|
|
|
Some(w @ '0')
|
|
|
|
|
| Some(w @ '1')
|
|
|
|
|
| Some(w @ '5')
|
|
|
|
|
| Some(w @ '7')
|
|
|
|
|
| Some(w @ '8')
|
|
|
|
|
| Some(w @ '9')
|
|
|
|
|
| Some(w @ 'g')
|
|
|
|
|
| Some(w @ 'I')
|
|
|
|
|
| Some(w @ 'p')
|
|
|
|
|
| Some(w @ 'h')
|
|
|
|
|
| Some(w @ 's') => {
|
|
|
|
|
self.add_link(
|
|
|
|
|
*line.offset(0 as libc::c_int as isize),
|
|
|
|
|
CString::from_raw(fields[0] as *mut i8).into_string().unwrap(),
|
|
|
|
|
CString::from_raw(fields[2] as *mut i8).into_string().unwrap(),
|
|
|
|
|
CString::from_raw(fields[3] as *mut i8)
|
|
|
|
|
.into_string()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.parse()
|
|
|
|
|
.unwrap(),
|
|
|
|
|
CString::from_raw(fields[1] as *mut i8).into_string().unwrap(),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
printf(
|
|
|
|
|
b"miss [%c]: %s\n\x00" as *const u8 as *const libc::c_char,
|
|
|
|
|
*line.offset(0 as libc::c_int as isize) as libc::c_int,
|
|
|
|
|
fields[0],
|
|
|
|
|
w,
|
|
|
|
|
fields[0].to_string(),
|
|
|
|
|
fields[2].to_string(),
|
|
|
|
|
fields[3].parse().unwrap_or(70), // todo oof
|
|
|
|
|
fields[1].to_string(),
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
Some(x) => println!("miss [{}]: {}", x, fields[0]),
|
|
|
|
|
None => (),
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub unsafe fn view_directory(
|
|
|
|
@ -579,8 +493,8 @@ impl BrowserState {
|
|
|
|
|
}
|
|
|
|
|
i = 0 as libc::c_int;
|
|
|
|
|
while i < head_read {
|
|
|
|
|
self.handle_directory_line(head[i as usize].as_mut_ptr());
|
|
|
|
|
i += 1
|
|
|
|
|
self.handle_directory_line(&CString::from_raw(head[i as usize].as_mut_ptr()).into_string().unwrap());
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
while read_line(
|
|
|
|
|
srvfd,
|
|
|
|
@ -588,14 +502,14 @@ impl BrowserState {
|
|
|
|
|
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
|
|
|
|
|
) != 0
|
|
|
|
|
{
|
|
|
|
|
self.handle_directory_line(line.as_mut_ptr());
|
|
|
|
|
self.handle_directory_line(&CString::from_raw(line.as_mut_ptr()).into_string().unwrap());
|
|
|
|
|
}
|
|
|
|
|
close(srvfd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub unsafe fn view_file(
|
|
|
|
|
&mut self,
|
|
|
|
|
mut cmd: *const libc::c_char,
|
|
|
|
|
mut cmd: &str,
|
|
|
|
|
mut host: &str,
|
|
|
|
|
mut port: usize,
|
|
|
|
|
mut selector: &str,
|
|
|
|
@ -607,9 +521,7 @@ impl BrowserState {
|
|
|
|
|
let mut buffer: [libc::c_char; 1024] = [0; 1024];
|
|
|
|
|
let mut argv: [*mut libc::c_char; 32] = [0 as *mut libc::c_char; 32];
|
|
|
|
|
let mut p: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
|
|
|
if check_option_true(
|
|
|
|
|
CString::new(self.config.verbose.clone()).unwrap().into_raw(),
|
|
|
|
|
) != 0
|
|
|
|
|
if self.config.verbose
|
|
|
|
|
{
|
|
|
|
|
println!("h({}) p({}) s({})", host, port, selector);
|
|
|
|
|
}
|
|
|
|
@ -656,15 +568,10 @@ impl BrowserState {
|
|
|
|
|
CString::new(self.tmpfilename.clone()).unwrap().into_raw();
|
|
|
|
|
argv[j as usize] = 0 as *mut libc::c_char;
|
|
|
|
|
/* fork and execute */
|
|
|
|
|
if check_option_true(
|
|
|
|
|
CString::new(self.config.verbose.clone()).unwrap().into_raw(),
|
|
|
|
|
) != 0
|
|
|
|
|
if self.config.verbose
|
|
|
|
|
{
|
|
|
|
|
printf(
|
|
|
|
|
b"executing: %s %s\n\x00" as *const u8 as *const libc::c_char,
|
|
|
|
|
cmd,
|
|
|
|
|
self.tmpfilename.as_mut_ptr(),
|
|
|
|
|
); /* to wait for browsers etc. that return immediatly */
|
|
|
|
|
println!("executing: {} {}", cmd, self.tmpfilename);
|
|
|
|
|
/* to wait for browsers etc. that return immediately */
|
|
|
|
|
}
|
|
|
|
|
pid = fork();
|
|
|
|
|
if pid == 0 as libc::c_int {
|
|
|
|
@ -866,9 +773,7 @@ impl BrowserState {
|
|
|
|
|
match w {
|
|
|
|
|
'0' => {
|
|
|
|
|
self.view_file(
|
|
|
|
|
CString::new(self.config.cmd_text.clone())
|
|
|
|
|
.unwrap()
|
|
|
|
|
.into_raw(),
|
|
|
|
|
&self.config.cmd_text,
|
|
|
|
|
&(*l).host,
|
|
|
|
|
(*l).port,
|
|
|
|
|
&(*l).selector,
|
|
|
|
@ -893,9 +798,7 @@ impl BrowserState {
|
|
|
|
|
}
|
|
|
|
|
'f' | 'I' | 'p' => {
|
|
|
|
|
self.view_file(
|
|
|
|
|
CString::new(self.config.cmd_image.clone())
|
|
|
|
|
.unwrap()
|
|
|
|
|
.into_raw(),
|
|
|
|
|
&self.config.cmd_image,
|
|
|
|
|
&(*l).host,
|
|
|
|
|
(*l).port,
|
|
|
|
|
&(*l).selector,
|
|
|
|
@ -903,9 +806,7 @@ impl BrowserState {
|
|
|
|
|
}
|
|
|
|
|
'h' => {
|
|
|
|
|
self.view_file(
|
|
|
|
|
CString::new(self.config.cmd_browser.clone())
|
|
|
|
|
.unwrap()
|
|
|
|
|
.into_raw(),
|
|
|
|
|
&self.config.cmd_browser,
|
|
|
|
|
&(*l).host,
|
|
|
|
|
(*l).port,
|
|
|
|
|
&(*l).selector,
|
|
|
|
@ -913,9 +814,7 @@ impl BrowserState {
|
|
|
|
|
}
|
|
|
|
|
's' => {
|
|
|
|
|
self.view_file(
|
|
|
|
|
CString::new(self.config.cmd_player.clone())
|
|
|
|
|
.unwrap()
|
|
|
|
|
.into_raw(),
|
|
|
|
|
&self.config.cmd_player,
|
|
|
|
|
&(*l).host,
|
|
|
|
|
(*l).port,
|
|
|
|
|
&(*l).selector,
|
|
|
|
@ -1147,11 +1046,6 @@ pub fn banner(to_error: bool) {
|
|
|
|
|
println!("cgo 0.6.1 Copyright (c) 2020 Sebastian Steinhauer");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub unsafe fn check_option_true(mut option: *const libc::c_char) -> libc::c_int {
|
|
|
|
|
return (strcasecmp(option, b"false\x00" as *const u8 as *const libc::c_char) != 0
|
|
|
|
|
&& strcasecmp(option, b"off\x00" as *const u8 as *const libc::c_char) != 0)
|
|
|
|
|
as libc::c_int;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub unsafe fn dial(mut host: &str, mut port: usize, mut selector: &str) -> libc::c_int {
|
|
|
|
|
let mut hints: addrinfo = addrinfo {
|
|
|
|
@ -1202,7 +1096,6 @@ pub unsafe fn dial(mut host: &str, mut port: usize, mut selector: &str) -> libc:
|
|
|
|
|
}
|
|
|
|
|
r = (*r).ai_next
|
|
|
|
|
}
|
|
|
|
|
freeaddrinfo(res);
|
|
|
|
|
if r.is_null() {
|
|
|
|
|
eprintln!("error: cannot connect to host '{}:{}'", host, port);
|
|
|
|
|
return -(1 as libc::c_int);
|
|
|
|
|