You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1626 lines
46 KiB
Rust

#![allow(
dead_code,
mutable_transmutes,
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
unused_assignments,
unused_mut
)]
#![register_tool(c2rust)]
#![feature(const_raw_ptr_to_usize_cast, extern_types, main, register_tool)]
extern crate libc;
#[macro_use] extern crate lazy_static;
use std::env;
use std::process::exit;
use std::thread::sleep;
use std::time::Duration;
use std::ffi::{CStr, CString};
use std::mem;
use std::ptr;
extern "C" {
pub type _IO_wide_data;
pub type _IO_codecvt;
pub type _IO_marker;
#[no_mangle]
fn waitpid(
__pid: __pid_t,
__stat_loc: *mut libc::c_int,
__options: libc::c_int,
) -> __pid_t;
#[no_mangle]
fn socket(
__domain: libc::c_int,
__type: libc::c_int,
__protocol: libc::c_int,
) -> libc::c_int;
#[no_mangle]
fn connect(
__fd: libc::c_int,
__addr: *const sockaddr,
__len: socklen_t,
) -> libc::c_int;
#[no_mangle]
fn getaddrinfo(
__name: *const libc::c_char,
__service: *const libc::c_char,
__req: *const addrinfo,
__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;
#[no_mangle]
fn read(__fd: libc::c_int, __buf: *mut libc::c_void, __nbytes: size_t) -> ssize_t;
#[no_mangle]
fn write(__fd: libc::c_int, __buf: *const libc::c_void, __n: size_t) -> ssize_t;
#[no_mangle]
fn execvp(
__file: *const libc::c_char,
__argv: *const *mut libc::c_char,
) -> libc::c_int;
#[no_mangle]
fn execlp(
__file: *const libc::c_char,
__arg: *const libc::c_char,
_: ...
) -> libc::c_int;
#[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(
_: *mut libc::c_char,
_: libc::c_ulong,
_: *const libc::c_char,
_: ...
) -> 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,
_: libc::c_ulong,
) -> *mut libc::c_void;
#[no_mangle]
fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char;
#[no_mangle]
fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
#[no_mangle]
fn strncmp(
_: *const libc::c_char,
_: *const libc::c_char,
_: libc::c_ulong,
) -> libc::c_int;
#[no_mangle]
fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
#[no_mangle]
fn strrchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
#[no_mangle]
fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
#[no_mangle]
fn strlen(_: *const libc::c_char) -> libc::c_ulong;
#[no_mangle]
fn strerror(_: libc::c_int) -> *mut libc::c_char;
}
pub type __off_t = libc::c_long;
pub type __off64_t = libc::c_long;
pub type __pid_t = libc::c_int;
pub type __ssize_t = libc::c_long;
pub type __socklen_t = libc::c_uint;
pub type pid_t = __pid_t;
pub type ssize_t = __ssize_t;
pub type size_t = libc::c_ulong;
pub type socklen_t = __socklen_t;
pub type __socket_type = libc::c_uint;
pub const SOCK_NONBLOCK: __socket_type = 2048;
pub const SOCK_CLOEXEC: __socket_type = 524288;
pub const SOCK_PACKET: __socket_type = 10;
pub const SOCK_DCCP: __socket_type = 6;
pub const SOCK_SEQPACKET: __socket_type = 5;
pub const SOCK_RDM: __socket_type = 4;
pub const SOCK_RAW: __socket_type = 3;
pub const SOCK_DGRAM: __socket_type = 2;
pub const SOCK_STREAM: __socket_type = 1;
pub type sa_family_t = libc::c_ushort;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr {
pub sa_family: sa_family_t,
pub sa_data: [libc::c_char; 14],
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct addrinfo {
pub ai_flags: libc::c_int,
pub ai_family: libc::c_int,
pub ai_socktype: libc::c_int,
pub ai_protocol: libc::c_int,
pub ai_addrlen: socklen_t,
pub ai_addr: *mut sockaddr,
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(Copy, Clone)]
pub struct Link {
pub next: *mut Link,
pub which: libc::c_char,
pub key: libc::c_short,
pub host: *mut libc::c_char,
pub port: *mut libc::c_char,
pub selector: *mut libc::c_char,
}
#[derive(Clone)]
pub struct Config {
pub start_uri: String, //[libc::c_char; 512],
pub cmd_text: String, //[libc::c_char; 512],
pub cmd_image: String, //[libc::c_char; 512],
pub cmd_browser: String, //[libc::c_char; 512],
pub cmd_player: String, //[libc::c_char; 512],
pub color_prompt: String, //[libc::c_char; 512],
pub color_selector: String, //[libc::c_char; 512],
pub verbose: String, //[libc::c_char; 512],
}
pub static mut tmpfilename: [libc::c_char; 256] = [0; 256];
pub static mut links: *mut Link = 0 as *const Link as *mut Link;
pub static mut history: *mut Link = 0 as *const Link as *mut Link;
pub static mut link_key: libc::c_int = 0;
pub static mut current_host: [libc::c_char; 512] = [0; 512];
pub static mut current_port: [libc::c_char; 64] = [0; 64];
pub static mut current_selector: [libc::c_char; 1024] = [0; 1024];
pub static mut parsed_host: [libc::c_char; 512] = [0; 512];
pub static mut parsed_port: [libc::c_char; 64] = [0; 64];
pub static mut parsed_selector: [libc::c_char; 1024] = [0; 1024];
pub static mut bookmarks: [[libc::c_char; 512]; 20] = [[0; 512]; 20];
lazy_static! {
pub static ref config: Config = Config {
start_uri: String::from("gopher://gopher.floodgap.com:70"),
cmd_text: String::from("less"),
cmd_image: String::from("display"),
cmd_browser: String::from("firefox"),
cmd_player: String::from("mplayer"),
color_prompt: String::from("1;34"),
color_selector: String::from("1;32"),
verbose: String::from("true"),
};
}
/* implementation */
pub fn usage() {
eprintln!("usage: cgo [-v] [-H] [gopher URI]");
exit(0);
}
#[no_mangle]
pub fn banner(to_error: bool) {
if to_error {
eprintln!("cgo 0.6.1 Copyright (c) 2020 Sebastian Steinhauer");
} else {
println!("cgo 0.6.1 Copyright (c) 2020 Sebastian Steinhauer");
}
}
#[no_mangle]
pub unsafe extern "C" 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;
}
#[no_mangle]
pub unsafe extern "C" fn parse_config_line(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(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(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(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(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(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(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(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(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 = &mut *(*bookmarks.as_mut_ptr().offset(j as isize))
.as_mut_ptr()
.offset(0 as libc::c_int as isize) as *mut libc::c_char;
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
}
i += 1;
*value.offset(i as isize) = 0 as libc::c_int as libc::c_char;
}
#[no_mangle]
pub unsafe extern "C" fn load_config(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 => {
parse_config_line(line.as_mut_ptr());
fclose(fp);
return;
}
13 => ch = fgetc(fp),
10 => {
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 extern "C" fn init_config() {
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 */
snprintf(
CString::new(config.start_uri.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"gopher://gopher.floodgap.com:70\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.cmd_text.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"less\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.cmd_image.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"display\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.cmd_browser.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"firefox\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.cmd_player.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"mplayer\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.color_prompt.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"1;34\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.color_selector.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"1;32\x00" as *const u8 as *const libc::c_char,
);
snprintf(
CString::new(config.verbose.clone()).unwrap().into_raw(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
b"true\x00" as *const u8 as *const libc::c_char,
);
i = 0 as libc::c_int;
while i < 20 as libc::c_int {
bookmarks[i as usize][0 as libc::c_int as usize] =
0 as libc::c_int as libc::c_char;
i += 1
}
/* read configs */
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,
);
load_config(filename.as_mut_ptr());
};
}
pub unsafe extern "C" fn dial(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
) -> libc::c_int {
let mut hints: addrinfo = addrinfo {
ai_flags: 0,
ai_family: 0,
ai_socktype: 0,
ai_protocol: 0,
ai_addrlen: 0,
ai_addr: 0 as *mut sockaddr,
ai_canonname: 0 as *mut libc::c_char,
ai_next: 0 as *mut addrinfo,
};
let mut res: *mut addrinfo = 0 as *mut addrinfo;
let mut r: *mut addrinfo = 0 as *mut addrinfo;
let mut srv: libc::c_int = -(1 as libc::c_int);
let mut l: libc::c_int = 0;
let mut request: [libc::c_char; 512] = [0; 512];
memset(
&mut hints as *mut addrinfo as *mut libc::c_void,
0 as libc::c_int,
mem::size_of::<addrinfo>() as libc::c_ulong,
);
hints.ai_family = 0 as libc::c_int;
hints.ai_socktype = SOCK_STREAM as libc::c_int;
if getaddrinfo(host, port, &mut hints, &mut res) != 0 as libc::c_int {
eprintln!(
"error: cannot resolve hostname '{}:{}': {}",
CStr::from_ptr(host).to_str().unwrap(),
CStr::from_ptr(port).to_str().unwrap(),
CStr::from_ptr(strerror(*__errno_location())).to_str().unwrap()
);
return -(1 as libc::c_int);
}
r = res;
while !r.is_null() {
srv = socket((*r).ai_family, (*r).ai_socktype, (*r).ai_protocol);
if !(srv == -(1 as libc::c_int)) {
if connect(srv, (*r).ai_addr, (*r).ai_addrlen) == 0 as libc::c_int {
break;
}
close(srv);
}
r = (*r).ai_next
}
freeaddrinfo(res);
if r.is_null() {
fprintf(
stderr,
b"error: cannot connect to host \'%s:%s\'\n\x00" as *const u8
as *const libc::c_char,
host,
port,
);
return -(1 as libc::c_int);
}
snprintf(
request.as_mut_ptr(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\r\n\x00" as *const u8 as *const libc::c_char,
selector,
);
l = strlen(request.as_mut_ptr()) as libc::c_int;
if write(srv, request.as_mut_ptr() as *const libc::c_void, l as size_t)
!= l as libc::c_long
{
fprintf(
stderr,
b"error: cannot complete request\n\x00" as *const u8 as *const libc::c_char,
);
close(srv);
return -(1 as libc::c_int);
}
return srv;
}
pub unsafe extern "C" fn read_line(
mut fd: libc::c_int,
mut buf: *mut libc::c_char,
mut buf_len: size_t,
) -> libc::c_int {
let mut i: size_t = 0 as libc::c_int as size_t;
let mut c: libc::c_char = 0 as libc::c_int as libc::c_char;
loop {
if read(
fd,
&mut c as *mut libc::c_char as *mut libc::c_void,
mem::size_of::<libc::c_char>() as libc::c_ulong,
) as libc::c_ulong
!= mem::size_of::<libc::c_char>() as libc::c_ulong
{
return 0 as libc::c_int;
}
if c as libc::c_int != '\r' as i32 {
let fresh3 = i;
i = i.wrapping_add(1);
*buf.offset(fresh3 as isize) = c
}
if !(c as libc::c_int != '\n' as i32 && i < buf_len) {
break;
}
}
*buf.offset(i.wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize) =
'\u{0}' as i32 as libc::c_char;
return 1 as libc::c_int;
}
pub unsafe extern "C" fn download_file(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
mut fd: libc::c_int,
) -> libc::c_int {
let mut srvfd: libc::c_int = 0;
let mut len: libc::c_int = 0;
let mut total: libc::c_ulong = 0 as libc::c_int as libc::c_ulong;
let mut buffer: [libc::c_char; 4096] = [0; 4096];
if check_option_true(CString::new(config.verbose.clone()).unwrap().into_raw()) != 0 {
printf(
b"downloading [%s]...\r\x00" as *const u8 as *const libc::c_char,
selector,
);
}
srvfd = dial(host, port, selector);
if srvfd == -(1 as libc::c_int) {
printf(
b"\x1b[2Kerror: downloading [%s] failed\n\x00" as *const u8
as *const libc::c_char,
selector,
);
close(fd);
return 0 as libc::c_int;
}
loop {
len = read(
srvfd,
buffer.as_mut_ptr() as *mut libc::c_void,
mem::size_of::<[libc::c_char; 4096]>() as libc::c_ulong,
) as libc::c_int;
if !(len > 0 as libc::c_int) {
break;
}
write(fd, buffer.as_mut_ptr() as *const libc::c_void, len as size_t);
total = total.wrapping_add(len as libc::c_ulong);
if check_option_true(CString::new(config.verbose.clone()).unwrap().into_raw()) != 0 {
printf(
b"downloading [%s] (%ld kb)...\r\x00" as *const u8 as *const libc::c_char,
selector,
total.wrapping_div(1024 as libc::c_int as libc::c_ulong),
);
}
}
close(fd);
close(srvfd);
if check_option_true(CString::new(config.verbose.clone()).unwrap().into_raw()) != 0 {
printf(
b"\x1b[2Kdownloading [%s] complete\n\x00" as *const u8 as *const libc::c_char,
selector,
);
}
return 1 as libc::c_int;
}
pub unsafe extern "C" fn download_temp(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
) -> libc::c_int {
let mut tmpfd: libc::c_int = 0;
strcpy(
tmpfilename.as_mut_ptr(),
b"/tmp/cgoXXXXXX\x00" as *const u8 as *const libc::c_char,
);
tmpfd = mkstemp(tmpfilename.as_mut_ptr());
if tmpfd == -(1 as libc::c_int) {
fputs(
b"error: unable to create tmp file\n\x00" as *const u8 as *const libc::c_char,
stderr,
);
return 0 as libc::c_int;
}
if download_file(host, port, selector, tmpfd) == 0 {
unlink(tmpfilename.as_mut_ptr());
return 0 as libc::c_int;
}
return 1 as libc::c_int;
}
pub unsafe extern "C" fn make_key(
mut c1: libc::c_char,
mut c2: libc::c_char,
mut c3: libc::c_char,
) -> libc::c_int {
if c1 == 0 || c2 == 0 {
return -(1 as libc::c_int);
}
if c3 == 0 {
return (c1 as libc::c_int - 'a' as i32)
* ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
+ (c2 as libc::c_int - 'a' as i32);
} else {
return (c1 as libc::c_int - 'a' as i32 + 1 as libc::c_int)
* ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
* ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
+ (c2 as libc::c_int - 'a' as i32)
* ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
+ (c3 as libc::c_int - 'a' as i32);
};
}
pub unsafe extern "C" fn make_key_str(
mut key: libc::c_int,
mut c1: *mut libc::c_char,
mut c2: *mut libc::c_char,
mut c3: *mut libc::c_char,
) {
if key
< ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
* ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
{
*c1 = ('a' as i32 + key / ('z' as i32 - 'a' as i32 + 1 as libc::c_int))
as libc::c_char;
*c2 = ('a' as i32 + key % ('z' as i32 - 'a' as i32 + 1 as libc::c_int))
as libc::c_char;
*c3 = 0 as libc::c_int as libc::c_char
} else {
*c1 = ('a' as i32
+ key
/ (('z' as i32 - 'a' as i32 + 1 as libc::c_int)
* ('z' as i32 - 'a' as i32 + 1 as libc::c_int))
- 1 as libc::c_int) as libc::c_char;
*c2 = ('a' as i32
+ key / ('z' as i32 - 'a' as i32 + 1 as libc::c_int)
% ('z' as i32 - 'a' as i32 + 1 as libc::c_int)) as libc::c_char;
*c3 = ('a' as i32 + key % ('z' as i32 - 'a' as i32 + 1 as libc::c_int))
as libc::c_char
};
}
pub unsafe extern "C" fn add_link(
mut which: libc::c_char,
mut name: *const libc::c_char,
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
) {
let mut link: *mut Link = 0 as *mut Link;
let mut a: libc::c_char = 0 as libc::c_int as libc::c_char;
let mut b: libc::c_char = 0 as libc::c_int as libc::c_char;
let mut c: libc::c_char = 0 as libc::c_int as libc::c_char;
if host.is_null() || port.is_null() || selector.is_null() {
return;
}
link = calloc(
1 as libc::c_int as libc::c_ulong,
mem::size_of::<Link>() as libc::c_ulong,
) as *mut Link;
(*link).which = which;
(*link).key = link_key as libc::c_short;
(*link).host = strdup(host);
(*link).port = strdup(port);
(*link).selector = strdup(selector);
if links.is_null() {
(*link).next = 0 as *mut Link
} else {
(*link).next = links
}
links = link;
let fresh4 = link_key;
link_key = link_key + 1;
make_key_str(fresh4, &mut a, &mut b, &mut c);
printf(
b"\x1b[%sm%c%c%c\x1b[0m \x1b[1m%s\x1b[0m\n\x00" as *const u8
as *const libc::c_char,
CString::new(config.color_selector.clone()).unwrap().into_raw(),
a as libc::c_int,
b as libc::c_int,
c as libc::c_int,
name,
);
}
pub unsafe extern "C" fn clear_links() {
let mut link: *mut Link = 0 as *mut Link;
let mut next: *mut Link = 0 as *mut Link;
link = links;
while !link.is_null() {
next = (*link).next;
free((*link).host as *mut libc::c_void);
free((*link).port as *mut libc::c_void);
free((*link).selector as *mut libc::c_void);
free(link as *mut libc::c_void);
link = next
}
links = 0 as *mut Link;
link_key = 0 as libc::c_int;
}
pub unsafe extern "C" fn add_history() {
let mut link: *mut Link = 0 as *mut Link;
link = calloc(
1 as libc::c_int as libc::c_ulong,
mem::size_of::<Link>() as libc::c_ulong,
) as *mut Link;
(*link).host = strdup(current_host.as_mut_ptr());
(*link).port = strdup(current_port.as_mut_ptr());
(*link).selector = strdup(current_selector.as_mut_ptr());
(*link).which = 0 as libc::c_int as libc::c_char;
(*link).key = 0 as libc::c_int as libc::c_short;
if history.is_null() {
(*link).next = 0 as *mut Link
} else {
(*link).next = history
}
history = link;
}
pub unsafe extern "C" fn handle_directory_line(mut line: *mut libc::c_char) {
let mut i: libc::c_int = 0;
let mut lp: *mut libc::c_char = 0 as *mut libc::c_char;
let mut last: *mut libc::c_char = 0 as *mut libc::c_char;
let mut fields: [*mut libc::c_char; 4] = [0 as *mut libc::c_char; 4];
/* tokenize */
i = 0 as libc::c_int;
while i < 4 as libc::c_int {
fields[i as usize] = 0 as *mut libc::c_char;
i += 1
}
last = &mut *line.offset(1 as libc::c_int as isize) as *mut libc::c_char;
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 = '\u{0}' as i32 as libc::c_char;
i += 1
}
lp = lp.offset(1)
}
/* 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 as libc::c_int as usize],
);
}
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 => {
add_link(
*line.offset(0 as libc::c_int as isize),
fields[0 as libc::c_int as usize],
fields[2 as libc::c_int as usize],
fields[3 as libc::c_int as usize],
fields[1 as libc::c_int as usize],
);
}
_ => {
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 as libc::c_int as usize],
);
}
};
}
pub unsafe extern "C" fn is_valid_directory_entry(
mut line: *const libc::c_char,
) -> libc::c_int {
match *line.offset(0 as libc::c_int as isize) as libc::c_int {
105 | 51 | 46 | 48 | 49 | 53 | 55 | 56 | 57 | 103 | 73 | 112 | 104 | 115 => {
/* some gopher servers use this */
return 1 as libc::c_int;
}
_ => return 0 as libc::c_int,
};
}
pub unsafe extern "C" fn view_directory(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
mut make_current: libc::c_int,
) {
let mut is_dir: libc::c_int = 0;
let mut srvfd: libc::c_int = 0;
let mut i: libc::c_int = 0;
let mut head_read: libc::c_int = 0;
let mut line: [libc::c_char; 1024] = [0; 1024];
let mut head: [[libc::c_char; 1024]; 5] = [[0; 1024]; 5];
srvfd = dial(host, port, selector);
if srvfd != -(1 as libc::c_int) {
/* only adapt current prompt when successful */
/* make history entry */
if make_current != 0 {
add_history();
}
/* don't overwrite the current_* things... */
if host != current_host.as_mut_ptr() as *const libc::c_char {
snprintf(
current_host.as_mut_ptr(),
mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
host,
); /* clear links *AFTER* dialing out!! */
} /* quit if not successful */
if port != current_port.as_mut_ptr() as *const libc::c_char {
snprintf(
current_port.as_mut_ptr(),
mem::size_of::<[libc::c_char; 64]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
port,
);
}
if selector != current_selector.as_mut_ptr() as *const libc::c_char {
snprintf(
current_selector.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
selector,
);
}
}
clear_links();
if srvfd == -(1 as libc::c_int) {
return;
}
head_read = 0 as libc::c_int;
is_dir = 1 as libc::c_int;
while head_read < 5 as libc::c_int
&& read_line(
srvfd,
line.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
) != 0
{
strcpy(head[head_read as usize].as_mut_ptr(), line.as_mut_ptr());
if is_valid_directory_entry(head[head_read as usize].as_mut_ptr()) == 0 {
is_dir = 0 as libc::c_int;
break;
} else {
head_read += 1
}
}
if is_dir == 0 {
puts(b"error: Not a directory.\x00" as *const u8 as *const libc::c_char);
close(srvfd);
return;
}
i = 0 as libc::c_int;
while i < head_read {
handle_directory_line(head[i as usize].as_mut_ptr());
i += 1
}
while read_line(
srvfd,
line.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
) != 0
{
handle_directory_line(line.as_mut_ptr());
}
close(srvfd);
}
pub unsafe extern "C" fn view_file(
mut cmd: *const libc::c_char,
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
) {
let mut pid: pid_t = 0;
let mut status: libc::c_int = 0;
let mut i: libc::c_int = 0;
let mut j: libc::c_int = 0;
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(config.verbose.clone()).unwrap().into_raw()) != 0 {
printf(
b"h(%s) p(%s) s(%s)\n\x00" as *const u8 as *const libc::c_char,
host,
port,
selector,
);
}
if download_temp(host, port, selector) == 0 {
return;
}
/* parsed command line string */
argv[0 as libc::c_int as usize] =
&mut *buffer.as_mut_ptr().offset(0 as libc::c_int as isize) as *mut libc::c_char;
p = cmd as *mut libc::c_char;
i = 0 as libc::c_int;
j = 1 as libc::c_int;
while *p as libc::c_int != 0
&& (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)
&& j < 30 as libc::c_int
{
if *p as libc::c_int == ' ' as i32 || *p as libc::c_int == '\t' as i32 {
let fresh5 = i;
i = i + 1;
buffer[fresh5 as usize] = 0 as libc::c_int as libc::c_char;
let fresh6 = j;
j = j + 1;
argv[fresh6 as usize] =
&mut *buffer.as_mut_ptr().offset(i as isize) as *mut libc::c_char;
while *p as libc::c_int == ' ' as i32 || *p as libc::c_int == '\t' as i32 {
p = p.offset(1)
}
} else {
let fresh7 = p;
p = p.offset(1);
let fresh8 = i;
i = i + 1;
buffer[fresh8 as usize] = *fresh7
}
}
buffer[i as usize] = 0 as libc::c_int as libc::c_char;
let fresh9 = j;
j = j + 1;
argv[fresh9 as usize] = tmpfilename.as_mut_ptr();
argv[j as usize] = 0 as *mut libc::c_char;
/* fork and execute */
if check_option_true(CString::new(config.verbose.clone()).unwrap().into_raw()) != 0 {
printf(
b"executing: %s %s\n\x00" as *const u8 as *const libc::c_char,
cmd,
tmpfilename.as_mut_ptr(),
); /* to wait for browsers etc. that return immediatly */
}
pid = fork();
if pid == 0 as libc::c_int {
if execvp(
argv[0 as libc::c_int as usize],
argv.as_mut_ptr() as *const *mut libc::c_char,
) == -(1 as libc::c_int)
{
puts(b"error: execvp() failed!\x00" as *const u8 as *const libc::c_char);
}
} else if pid == -(1 as libc::c_int) {
puts(b"error: fork() failed\x00" as *const u8 as *const libc::c_char);
}
sleep(Duration::from_secs(1));
waitpid(pid, &mut status, 0 as libc::c_int);
unlink(tmpfilename.as_mut_ptr());
}
pub unsafe extern "C" fn view_telnet(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
) {
let mut pid: pid_t = 0;
let mut status: libc::c_int = 0;
printf(
b"executing: %s %s %s\n\x00" as *const u8 as *const libc::c_char,
b"telnet\x00" as *const u8 as *const libc::c_char,
host,
port,
);
pid = fork();
if pid == 0 as libc::c_int {
if execlp(
b"telnet\x00" as *const u8 as *const libc::c_char,
b"telnet\x00" as *const u8 as *const libc::c_char,
host,
port,
0 as *mut libc::c_void,
) == -(1 as libc::c_int)
{
puts(b"error: execlp() failed!\x00" as *const u8 as *const libc::c_char);
}
} else if pid == -(1 as libc::c_int) {
puts(b"error: fork() failed!\x00" as *const u8 as *const libc::c_char);
}
waitpid(pid, &mut status, 0 as libc::c_int);
puts(b"(done)\x00" as *const u8 as *const libc::c_char);
}
pub unsafe extern "C" fn view_download(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
) {
let mut fd: libc::c_int = 0;
let mut filename: [libc::c_char; 1024] = [0; 1024];
let mut line: [libc::c_char; 1024] = [0; 1024];
snprintf(
filename.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
b"%s\x00" as *const u8 as *const libc::c_char,
strrchr(selector, '/' as i32).offset(1 as libc::c_int as isize),
);
printf(
b"enter filename for download [%s]: \x00" as *const u8 as *const libc::c_char,
filename.as_mut_ptr(),
);
if read_line(
0 as libc::c_int,
line.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
) == 0
{
puts(b"download aborted\x00" as *const u8 as *const libc::c_char);
return;
}
if strlen(line.as_mut_ptr()) > 0 as libc::c_int as libc::c_ulong {
strcpy(filename.as_mut_ptr(), line.as_mut_ptr());
}
fd = open(
filename.as_mut_ptr(),
0o100 as libc::c_int | 0o1 as libc::c_int,
0o400 as libc::c_int | 0o200 as libc::c_int,
);
if fd == -(1 as libc::c_int) {
printf(
b"error: unable to create file [%s]: %s\n\x00" as *const u8
as *const libc::c_char,
filename.as_mut_ptr(),
strerror(*__errno_location()),
);
return;
}
if download_file(host, port, selector, fd) == 0 {
printf(
b"error: unable to download [%s]\n\x00" as *const u8 as *const libc::c_char,
selector,
);
unlink(filename.as_mut_ptr());
return;
};
}
pub unsafe extern "C" fn view_search(
mut host: *const libc::c_char,
mut port: *const libc::c_char,
mut selector: *const libc::c_char,
) {
let mut search_selector: [libc::c_char; 1024] = [0; 1024];
let mut line: [libc::c_char; 1024] = [0; 1024];
printf(b"enter search string: \x00" as *const u8 as *const libc::c_char);
if read_line(
0 as libc::c_int,
line.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
) == 0
{
puts(b"search aborted\x00" as *const u8 as *const libc::c_char);
return;
}
snprintf(
search_selector.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
b"%s\t%s\x00" as *const u8 as *const libc::c_char,
selector,
line.as_mut_ptr(),
);
view_directory(host, port, search_selector.as_mut_ptr(), 1 as libc::c_int);
}
pub unsafe extern "C" fn view_history(mut key: libc::c_int) {
let mut history_key: libc::c_int = 0 as libc::c_int;
let mut a: libc::c_char = 0;
let mut b: libc::c_char = 0;
let mut c: libc::c_char = 0;
let mut link: *mut Link = 0 as *mut Link;
if history.is_null() {
puts(b"(empty history)\x00" as *const u8 as *const libc::c_char);
return;
}
if key < 0 as libc::c_int {
puts(b"(history)\x00" as *const u8 as *const libc::c_char);
link = history;
while !link.is_null() {
let fresh10 = history_key;
history_key = history_key + 1;
make_key_str(fresh10, &mut a, &mut b, &mut c);
printf(
b"\x1b[%sm%c%c%c\x1b[0m \x1b[1m%s:%s/1%s\x1b[0m\n\x00" as *const u8
as *const libc::c_char,
b"1;32\x00" as *const u8 as *const libc::c_char,
a as libc::c_int,
b as libc::c_int,
c as libc::c_int,
(*link).host,
(*link).port,
(*link).selector,
);
link = (*link).next
}
} else {
/* traverse history list */
link = history;
while !link.is_null() {
if history_key == key {
view_directory(
(*link).host,
(*link).port,
(*link).selector,
0 as libc::c_int,
);
return;
}
link = (*link).next;
history_key += 1
}
puts(b"history item not found\x00" as *const u8 as *const libc::c_char);
};
}
pub unsafe extern "C" fn view_bookmarks(mut key: libc::c_int) {
let mut i: libc::c_int = 0;
let mut a: libc::c_char = 0;
let mut b: libc::c_char = 0;
let mut c: libc::c_char = 0;
if key < 0 as libc::c_int {
puts(b"(bookmarks)\x00" as *const u8 as *const libc::c_char);
i = 0 as libc::c_int;
while i < 20 as libc::c_int {
if bookmarks[i as usize][0 as libc::c_int as usize] != 0 {
make_key_str(i, &mut a, &mut b, &mut c);
printf(
b"\x1b[%sm%c%c%c\x1b[0m \x1b[1m%s\x1b[0m\n\x00" as *const u8
as *const libc::c_char,
b"1;32\x00" as *const u8 as *const libc::c_char,
a as libc::c_int,
b as libc::c_int,
c as libc::c_int,
&mut *(*bookmarks.as_mut_ptr().offset(i as isize))
.as_mut_ptr()
.offset(0 as libc::c_int as isize) as *mut libc::c_char,
);
}
i += 1
}
} else {
i = 0 as libc::c_int;
while i < 20 as libc::c_int {
if bookmarks[i as usize][0 as libc::c_int as usize] as libc::c_int != 0
&& i == key
{
if parse_uri(
&mut *(*bookmarks.as_mut_ptr().offset(i as isize))
.as_mut_ptr()
.offset(0 as libc::c_int as isize),
) != 0
{
view_directory(
parsed_host.as_mut_ptr(),
parsed_port.as_mut_ptr(),
parsed_selector.as_mut_ptr(),
0 as libc::c_int,
);
} else {
printf(
b"invalid gopher URI: %s\x00" as *const u8 as *const libc::c_char,
&mut *(*bookmarks.as_mut_ptr().offset(i as isize))
.as_mut_ptr()
.offset(0 as libc::c_int as isize) as *mut libc::c_char,
);
}
return;
}
i += 1
}
};
}
pub unsafe extern "C" fn pop_history() {
let mut next: *mut Link = 0 as *mut Link;
if history.is_null() {
puts(b"(empty history)\x00" as *const u8 as *const libc::c_char);
return;
}
/* reload page from history (and don't count as history) */
view_directory(
(*history).host,
(*history).port,
(*history).selector,
0 as libc::c_int,
);
/* history is history... :) */
next = (*history).next;
free((*history).host as *mut libc::c_void);
free((*history).port as *mut libc::c_void);
free((*history).selector as *mut libc::c_void);
free(history as *mut libc::c_void);
history = next;
}
pub unsafe extern "C" fn follow_link(mut key: libc::c_int) -> libc::c_int {
let mut link: *mut Link = 0 as *mut Link;
link = links;
while !link.is_null() {
if (*link).key as libc::c_int != key {
link = (*link).next
} else {
match (*link).which as libc::c_int {
48 => {
view_file(
CString::new(config.cmd_text.clone())
.unwrap()
.into_raw(),
(*link).host,
(*link).port,
(*link).selector,
);
}
49 => {
view_directory(
(*link).host,
(*link).port,
(*link).selector,
1 as libc::c_int,
);
}
55 => {
view_search((*link).host, (*link).port, (*link).selector);
}
53 | 57 => {
view_download((*link).host, (*link).port, (*link).selector);
}
56 => {
view_telnet((*link).host, (*link).port);
}
103 | 73 | 112 => {
view_file(
CString::new(config.cmd_image.clone())
.unwrap()
.into_raw(),
(*link).host,
(*link).port,
(*link).selector,
);
}
104 => {
view_file(
CString::new(config.cmd_browser.clone())
.unwrap()
.into_raw(),
(*link).host,
(*link).port,
(*link).selector,
);
}
115 => {
view_file(
CString::new(config.cmd_player.clone())
.unwrap()
.into_raw(),
(*link).host,
(*link).port,
(*link).selector,
);
}
_ => {
printf(
b"missing handler [%c]\n\x00" as *const u8 as *const libc::c_char,
(*link).which as libc::c_int,
);
}
}
return 1 as libc::c_int;
}
/* return the array is broken after view! */
}
return 0 as libc::c_int;
}
pub unsafe extern "C" fn download_link(mut key: libc::c_int) {
let mut link: *mut Link = 0 as *mut Link;
link = links;
while !link.is_null() {
if (*link).key as libc::c_int != key {
link = (*link).next
} else {
view_download((*link).host, (*link).port, (*link).selector);
return;
}
}
puts(b"link not found\x00" as *const u8 as *const libc::c_char);
}
/* function prototypes */
pub unsafe extern "C" fn parse_uri(mut uri: *const libc::c_char) -> libc::c_int {
let mut i: libc::c_int = 0;
/* strip gopher:// */
if strncmp(
uri,
b"gopher://\x00" as *const u8 as *const libc::c_char,
9 as libc::c_int as libc::c_ulong,
) == 0
{
uri = uri.offset(9 as libc::c_int as isize)
}
/* parse host */
i = 0 as libc::c_int;
while *uri as libc::c_int != 0
&& *uri as libc::c_int != ':' as i32
&& *uri as libc::c_int != '/' as i32
{
if *uri as libc::c_int != ' ' as i32
&& (i as libc::c_ulong)
< (mem::size_of::<[libc::c_char; 512]>() as libc::c_ulong)
.wrapping_sub(1 as libc::c_int as libc::c_ulong)
{
let fresh11 = i;
i = i + 1;
parsed_host[fresh11 as usize] = *uri
}
uri = uri.offset(1)
}
if i > 0 as libc::c_int {
parsed_host[i as usize] = 0 as libc::c_int as libc::c_char
} else {
return 0 as libc::c_int;
}
/* parse port */
if *uri as libc::c_int == ':' as i32 {
uri = uri.offset(1);
i = 0 as libc::c_int;
while *uri as libc::c_int != 0 && *uri as libc::c_int != '/' as i32 {
if *uri as libc::c_int != ' ' as i32
&& (i as libc::c_ulong)
< (mem::size_of::<[libc::c_char; 64]>() as libc::c_ulong)
.wrapping_sub(1 as libc::c_int as libc::c_ulong)
{
let fresh12 = i;
i = i + 1;
parsed_port[fresh12 as usize] = *uri
}
uri = uri.offset(1)
}
parsed_port[i as usize] = 0 as libc::c_int as libc::c_char
} else {
snprintf(
parsed_port.as_mut_ptr(),
mem::size_of::<[libc::c_char; 64]>() as libc::c_ulong,
b"%d\x00" as *const u8 as *const libc::c_char,
70 as libc::c_int,
);
}
/* parse selector (ignore slash and selector type) */
if *uri != 0 {
uri = uri.offset(1)
}
if *uri != 0 {
uri = uri.offset(1)
}
i = 0 as libc::c_int;
while *uri as libc::c_int != 0
&& (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)
{
parsed_selector[i as usize] = *uri;
uri = uri.offset(1);
i += 1
}
parsed_selector[i as usize] = '\u{0}' as i32 as libc::c_char;
return 1 as libc::c_int;
}
unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> libc::c_int {
let mut i: libc::c_int = 0;
let mut line: [libc::c_char; 1024] = [0; 1024];
let mut uri: *mut libc::c_char = 0 as *mut libc::c_char;
/* copy defaults */
init_config();
uri = CString::new(config.start_uri.clone()).unwrap().into_raw();
/* parse command line */
i = 1 as libc::c_int;
while i < argc {
if *(*argv.offset(i as isize)).offset(0 as libc::c_int as isize) as libc::c_int
== '-' as i32
{
match *(*argv.offset(i as isize)).offset(1 as libc::c_int as isize)
as libc::c_int
{
72 => {
usage();
}
118 => {
banner(true);
exit(0);
}
_ => {
usage();
}
}
} else {
uri = *argv.offset(i as isize)
}
i += 1
}
/* parse uri */
if parse_uri(uri) == 0 {
banner(false);
eprintln!(
"invalid gopher URI: {}",
CStr::from_ptr(*argv.offset(i as isize)).to_str().unwrap()
);
exit(1);
}
/* main loop */
view_directory(
parsed_host.as_mut_ptr(),
parsed_port.as_mut_ptr(),
parsed_selector.as_mut_ptr(),
0 as libc::c_int,
); /* to display the prompt */
loop {
printf(
b"\x1b[%sm%s:%s%s\x1b[0m \x00" as *const u8 as *const libc::c_char,
CString::new(config.color_prompt.clone()).unwrap().into_raw(),
current_host.as_mut_ptr(),
current_port.as_mut_ptr(),
current_selector.as_mut_ptr(),
);
if read_line(
0 as libc::c_int,
line.as_mut_ptr(),
mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong,
) == 0
{
puts(b"QUIT\x00" as *const u8 as *const libc::c_char);
return 0 as libc::c_int;
}
i = strlen(line.as_mut_ptr()) as libc::c_int;
match line[0 as libc::c_int as usize] as libc::c_int {
63 => {
puts(b"? - help\n* - reload directory\n< - go back in history\n.[LINK] - download the given link\nH - show history\nH[LINK] - jump to the specified history item\nG[URI] - jump to the given gopher URI\nB - show bookmarks\nB[LINK] - jump to the specified bookmark item\nC^d - quit\x00"
as *const u8 as *const libc::c_char);
}
60 => {
pop_history();
}
42 => {
view_directory(
current_host.as_mut_ptr(),
current_port.as_mut_ptr(),
current_selector.as_mut_ptr(),
0 as libc::c_int,
);
}
46 => {
download_link(make_key(
line[1 as libc::c_int as usize],
line[2 as libc::c_int as usize],
line[3 as libc::c_int as usize],
));
}
72 => {
if i == 1 as libc::c_int || i == 3 as libc::c_int || i == 4 as libc::c_int
{
view_history(make_key(
line[1 as libc::c_int as usize],
line[2 as libc::c_int as usize],
line[3 as libc::c_int as usize],
));
}
}
71 => {
if parse_uri(&mut *line.as_mut_ptr().offset(1 as libc::c_int as isize))
!= 0
{
view_directory(
parsed_host.as_mut_ptr(),
parsed_port.as_mut_ptr(),
parsed_selector.as_mut_ptr(),
1 as libc::c_int,
);
} else {
puts(b"invalid gopher URI\x00" as *const u8 as *const libc::c_char);
}
}
66 => {
if i == 1 as libc::c_int || i == 3 as libc::c_int || i == 4 as libc::c_int
{
view_bookmarks(make_key(
line[1 as libc::c_int as usize],
line[2 as libc::c_int as usize],
line[3 as libc::c_int as usize],
));
}
}
_ => {
follow_link(make_key(
line[0 as libc::c_int as usize],
line[1 as libc::c_int as usize],
line[2 as libc::c_int as usize],
));
}
}
}
/* never get's here but stops cc complaining */
}
#[main]
pub fn main() {
let mut args: Vec<*mut libc::c_char> = Vec::new();
for arg in env::args() {
args.push(
CString::new(arg)
.expect("Failed to convert argument into CString.")
.into_raw(),
);
}
args.push(ptr::null_mut());
unsafe {
exit(main_0(
(args.len() - 1) as libc::c_int,
args.as_mut_ptr() as *mut *mut libc::c_char,
) as i32)
}
}