Program works now
This commit is contained in:
		
							parent
							
								
									157890be44
								
							
						
					
					
						commit
						9cef615779
					
				@ -2,7 +2,9 @@ use errors;
 | 
				
			|||||||
use fmt;
 | 
					use fmt;
 | 
				
			||||||
use fs;
 | 
					use fs;
 | 
				
			||||||
use getopt;
 | 
					use getopt;
 | 
				
			||||||
 | 
					use io;
 | 
				
			||||||
use os;
 | 
					use os;
 | 
				
			||||||
 | 
					use path;
 | 
				
			||||||
use strconv;
 | 
					use strconv;
 | 
				
			||||||
use strings;
 | 
					use strings;
 | 
				
			||||||
use unix;
 | 
					use unix;
 | 
				
			||||||
@ -12,12 +14,11 @@ const default_board = "general";
 | 
				
			|||||||
let name = "";
 | 
					let name = "";
 | 
				
			||||||
@init fn name() void = name = os::args[0];
 | 
					@init fn name() void = name = os::args[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let path: []str = [];
 | 
					let bulb_path: []str = [];
 | 
				
			||||||
@init fn path() void = path = strings::split(os::tryenv("BULBPATH", "/var/bulb"), ":");
 | 
					@init fn bulb_path() void = bulb_path = strings::split(os::tryenv("BULBPATH", "/var/bulb"), ":");
 | 
				
			||||||
@fini fn path() void = free(path);
 | 
					@fini fn bulb_path() void = free(bulb_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export fn main() void = {
 | 
					export fn main() void = {
 | 
				
			||||||
	// parse args
 | 
					 | 
				
			||||||
	const cmd = getopt::parse(
 | 
						const cmd = getopt::parse(
 | 
				
			||||||
		os::args,
 | 
							os::args,
 | 
				
			||||||
		"bulletin board",
 | 
							"bulletin board",
 | 
				
			||||||
@ -39,7 +40,7 @@ export fn main() void = {
 | 
				
			|||||||
		} else if (subcmd.0 == "read") {
 | 
							} else if (subcmd.0 == "read") {
 | 
				
			||||||
			match (subcmd_read(subcmd.1)) {
 | 
								match (subcmd_read(subcmd.1)) {
 | 
				
			||||||
			case errors::invalid =>
 | 
								case errors::invalid =>
 | 
				
			||||||
				getopt::printhelp(cmd);
 | 
									getopt::printhelp(os::stdout, name, cmd.help)!;
 | 
				
			||||||
				os::exit(os::status::FAILURE);
 | 
									os::exit(os::status::FAILURE);
 | 
				
			||||||
			case void => void;
 | 
								case void => void;
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
@ -60,28 +61,15 @@ fn subcmd_post(cmd: *getopt::command) void = {
 | 
				
			|||||||
		};
 | 
							};
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let location = match(look_up_board(board)) {
 | 
						let user_name = if (anonymous) void else get_user_name();
 | 
				
			||||||
	case let location: str =>
 | 
						let message   = strings::join(" ", cmd.args...);
 | 
				
			||||||
		yield location;
 | 
						defer free(message);
 | 
				
			||||||
	case void =>
 | 
						
 | 
				
			||||||
		fmt::errorf("{}: The board {} does not exist", name, board)!;
 | 
						match (post(board, user_name, message)) {
 | 
				
			||||||
		return;
 | 
						case let err: error =>
 | 
				
			||||||
 | 
							fmt::errorf("{}: Could not read {}: {}\n", name, board, strerror(err))!;
 | 
				
			||||||
 | 
						case void => void;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	let file = match(os::open(location, fs::flag::APPEND)) {
 | 
					 | 
				
			||||||
	case let file: io::file =>
 | 
					 | 
				
			||||||
		defer io::close(file);
 | 
					 | 
				
			||||||
		yield file;
 | 
					 | 
				
			||||||
	case let err: fs::error =>
 | 
					 | 
				
			||||||
		fmt::errorf(
 | 
					 | 
				
			||||||
			"{}: Can't make post: {}",
 | 
					 | 
				
			||||||
			name, fs::strerror(err));
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let user = 
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	fmt::fprintf(file, "{}: {}", user, message)!;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn subcmd_read(cmd: *getopt::command) (void | errors::invalid) = {
 | 
					fn subcmd_read(cmd: *getopt::command) (void | errors::invalid) = {
 | 
				
			||||||
@ -100,11 +88,15 @@ fn subcmd_read(cmd: *getopt::command) (void | errors::invalid) = {
 | 
				
			|||||||
		};
 | 
							};
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO
 | 
						match (read(board, number)) {
 | 
				
			||||||
 | 
						case let err: error =>
 | 
				
			||||||
 | 
							fmt::errorf("{}: Could not read {}: {}\n", name, board, strerror(err))!;
 | 
				
			||||||
 | 
						case void => void;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn subcmd_ls(cmd: *getopt::command) void = {
 | 
					fn subcmd_ls(cmd: *getopt::command) void = {
 | 
				
			||||||
	for (let directory .. path) {
 | 
						for (let directory .. bulb_path) {
 | 
				
			||||||
		match (list_boards_in(directory)) {
 | 
							match (list_boards_in(directory)) {
 | 
				
			||||||
		case let err: fs::error =>
 | 
							case let err: fs::error =>
 | 
				
			||||||
			fmt::errorf(
 | 
								fmt::errorf(
 | 
				
			||||||
@ -125,6 +117,20 @@ fn list_boards_in(directory: str) (void | fs::error) = {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//fn look_up_board(board: str, path: []str) (str | void) {
 | 
					fn look_up_board(board: str) (str | no_such_board) = {
 | 
				
			||||||
	// TODO
 | 
						static let buf = path::buffer { ... };
 | 
				
			||||||
//};
 | 
						for (let directory .. bulb_path) {
 | 
				
			||||||
 | 
							let location = path::set(&buf, directory, board)!;
 | 
				
			||||||
 | 
							match (os::stat(location)) {
 | 
				
			||||||
 | 
							case fs::filestat => return location;
 | 
				
			||||||
 | 
							case              => void;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						return no_such_board;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn get_user_name() str = {
 | 
				
			||||||
 | 
						// FIXME: could not find support for getting a username from a uid in
 | 
				
			||||||
 | 
						// hare. when it is added, use that here.
 | 
				
			||||||
 | 
						return os::tryenv("USER", "anonymous");
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										69
									
								
								cmd/bulb/operation.ha
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								cmd/bulb/operation.ha
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					use fs;
 | 
				
			||||||
 | 
					use fmt;
 | 
				
			||||||
 | 
					use io;
 | 
				
			||||||
 | 
					use os;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type no_such_board = !void;
 | 
				
			||||||
 | 
					type error = (io::error | fs::error | no_such_board);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn strerror(err: error) str = match(err) {
 | 
				
			||||||
 | 
					case no_such_board => return "No such board";
 | 
				
			||||||
 | 
					case let err: fs::error => return fs::strerror(err);
 | 
				
			||||||
 | 
					case let err: io::error => return io::strerror(err);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn read(board: str, number: int) (void | error) = {
 | 
				
			||||||
 | 
						let location = look_up_board(board)?;
 | 
				
			||||||
 | 
						let file = os::open(location)?;
 | 
				
			||||||
 | 
						defer io::close(file)!;
 | 
				
			||||||
 | 
						seek_to_nth_last_line(file, number)?;
 | 
				
			||||||
 | 
						io::copy(os::stdout, file)?;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn post(board: str, user_name: (str | void), message: str) (void | error) = {
 | 
				
			||||||
 | 
						let location = look_up_board(board)?;
 | 
				
			||||||
 | 
						let file = os::open(location, fs::flag::APPEND | fs::flag::WRONLY)?;
 | 
				
			||||||
 | 
						defer io::close(file)!;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						let user = match(user_name) {
 | 
				
			||||||
 | 
						case let user: str => yield(user);
 | 
				
			||||||
 | 
						case void => yield "anonymous";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						fmt::fprintf(file, "{}: {}\n", user, message)?;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn seek_to_nth_last_line(file: io::handle, number: int) (void | io::error) = {
 | 
				
			||||||
 | 
						let buffer: [256]u8 = [0...];
 | 
				
			||||||
 | 
						let end     = io::seek(file, 0, io::whence::END)?;
 | 
				
			||||||
 | 
						let step    = len(buffer): io::off;
 | 
				
			||||||
 | 
						let current = end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (true) {
 | 
				
			||||||
 | 
							// read a chunk in reverse, or stop if there is nothing left
 | 
				
			||||||
 | 
							let buffer = buffer[..];
 | 
				
			||||||
 | 
							if (current - step > 0) {
 | 
				
			||||||
 | 
								current -= step;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								buffer = buffer[..current];
 | 
				
			||||||
 | 
								current = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							io::seek(file, current, io::whence::SET)?;
 | 
				
			||||||
 | 
							let length = match (io::read(file, buffer)?) {
 | 
				
			||||||
 | 
							case let length: size => yield length;
 | 
				
			||||||
 | 
							case io::EOF          => break;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							io::seek(file, current, io::whence::SET)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// look for line breaks in that chunk
 | 
				
			||||||
 | 
							let buffer = buffer[..length];
 | 
				
			||||||
 | 
							for (let index = len(buffer): int - 1; index >= 0; index -= 1) {
 | 
				
			||||||
 | 
								if (buffer[index: size] == '\n') number -= 1;
 | 
				
			||||||
 | 
								if (number <= 0) {
 | 
				
			||||||
 | 
									io::seek(file, current + index: io::off, io::whence::SET)?;
 | 
				
			||||||
 | 
									return void;
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user