Implement most of the spec reusing scribe & nefthera code
This commit is contained in:
parent
e8b489dd6f
commit
612a98cfde
16 changed files with 225 additions and 25 deletions
|
|
@ -1,2 +1,6 @@
|
|||
(library
|
||||
(name tori))
|
||||
(name tori)
|
||||
(libraries unix)
|
||||
)
|
||||
|
||||
(include_subdirs qualified)
|
||||
|
|
|
|||
23
ocaml/lib/parsers/argument.ml
Normal file
23
ocaml/lib/parsers/argument.ml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
let interpret (past: Schema.schema) (input: string list): Schema.schema =
|
||||
|
||||
let future = { past with output = { message = "" } } in
|
||||
|
||||
(* say is useful when the only change to future is the output message *)
|
||||
let say (message: string) =
|
||||
{ future with output = { message = message } } in
|
||||
|
||||
(*
|
||||
TODO: return a schema with orders, instead of calling side-effects
|
||||
directly, making this more of a parser and less of a glorified switch
|
||||
*)
|
||||
match input with
|
||||
| "pkg" :: tail -> System.Package.merge past tail
|
||||
| "os" :: _ -> say (System.File.read "/etc/os-release")
|
||||
| "host" :: _ -> say (System.Process.Reader.read [||] "hostname").output
|
||||
| "echo" :: tail -> say (String.concat " " tail)
|
||||
| ("version" | "-v" | "--version") :: _ ->
|
||||
say (Schema.format_version future.meta.version)
|
||||
| ("help" | "-h" | "--help") :: _ -> say future.meta.help.long
|
||||
| head :: _ ->
|
||||
say ("Unrecognized command: " ^ head ^ "\n" ^ future.meta.help.short)
|
||||
| _ -> future
|
||||
2
ocaml/lib/qol.ml
Normal file
2
ocaml/lib/qol.ml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
let str_int = string_of_int
|
||||
let print = print_endline
|
||||
38
ocaml/lib/schema/schema.ml
Normal file
38
ocaml/lib/schema/schema.ml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
open Qol
|
||||
|
||||
type version = { major: int; minor: int; patch: int }
|
||||
type help = { short: string; long: string }
|
||||
type meta = { version: version; help: help }
|
||||
|
||||
type output = { message: string; }
|
||||
|
||||
type os = Unknown | FreeBSD | Void | Alpine
|
||||
type host = { os: os; name: string; }
|
||||
|
||||
type schema = { meta: meta; output: output; host: host; }
|
||||
|
||||
let seed: schema = {
|
||||
meta = {
|
||||
version = {
|
||||
major = 0;
|
||||
minor = 8;
|
||||
patch = 0;
|
||||
};
|
||||
help = {
|
||||
short = "Use 'tori help' for usage instructions";
|
||||
long = "<help message>";
|
||||
};
|
||||
};
|
||||
output = {
|
||||
message = "Use command 'help' for help";
|
||||
};
|
||||
host = {
|
||||
os = Unknown;
|
||||
name = "Unknown Host";
|
||||
};
|
||||
}
|
||||
|
||||
let format_version (version: version): string =
|
||||
"v" ^ str_int version.major ^
|
||||
"." ^ str_int version.minor ^
|
||||
"." ^ str_int version.patch
|
||||
14
ocaml/lib/system/file.ml
Normal file
14
ocaml/lib/system/file.ml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
let read_channel channel =
|
||||
let buffer = Buffer.create 4096 in
|
||||
let rec read () =
|
||||
let line = input_line channel in
|
||||
Buffer.add_string buffer line;
|
||||
Buffer.add_char buffer '\n';
|
||||
read ()
|
||||
in
|
||||
try read () with
|
||||
End_of_file -> Buffer.contents buffer
|
||||
|
||||
let read path =
|
||||
let channel = open_in path in
|
||||
read_channel channel
|
||||
15
ocaml/lib/system/package.ml
Normal file
15
ocaml/lib/system/package.ml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
let merge (schema: Schema.schema) (packages: string list) =
|
||||
|
||||
match packages with
|
||||
| [] -> { schema with output = { message = "No packages provided" } }
|
||||
| _ ->
|
||||
|
||||
let in_targets = List.flatten [["doas"; "apk"; "-i"; "add"]; packages] and
|
||||
out_targets = List.flatten [["doas"; "apk"; "-i"; "del"]; packages] in
|
||||
|
||||
Process.Fork.run "doas" in_targets;
|
||||
Process.Fork.run "doas" out_targets;
|
||||
|
||||
{ schema with output = {
|
||||
message = "Done: " ^ (String.concat "\n" packages)
|
||||
}}
|
||||
11
ocaml/lib/system/process/fork.ml
Normal file
11
ocaml/lib/system/process/fork.ml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
open Qol
|
||||
|
||||
let run (command: string) (arguments: string list) =
|
||||
match Unix.fork () with
|
||||
| 0 -> Unix.execvp command (Array.of_list arguments)
|
||||
| pid -> let (_, status) = Unix.waitpid [] pid in
|
||||
match status with
|
||||
| Unix.WEXITED 0 -> ()
|
||||
| Unix.WEXITED n -> print ("Process exited with code " ^ str_int n)
|
||||
| Unix.WSIGNALED n -> print ("Process terminated by signal " ^ str_int n)
|
||||
| Unix.WSTOPPED n -> print ("Process stopped by signal " ^ str_int n)
|
||||
45
ocaml/lib/system/process/reader.ml
Normal file
45
ocaml/lib/system/process/reader.ml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
open Qol
|
||||
|
||||
type output = { output: string; error: string; status: string; }
|
||||
|
||||
let handle_exit_status (status: Unix.process_status): string =
|
||||
match status with
|
||||
| Unix.WEXITED n -> "Exit " ^ str_int n
|
||||
| Unix.WSIGNALED n -> "Kill " ^ str_int n
|
||||
| Unix.WSTOPPED n -> "Stopped " ^ str_int n
|
||||
|
||||
let read (env: string array) (command: string): output =
|
||||
|
||||
let stdout, stdin, stderr = Unix.open_process_full command env in
|
||||
let in_buffer = Buffer.create 4096 in
|
||||
let err_buffer = Buffer.create 4096 in
|
||||
|
||||
let rec read_in () =
|
||||
let in_line = input_line stdout in
|
||||
Buffer.add_string in_buffer in_line;
|
||||
Buffer.add_char in_buffer '\n';
|
||||
read_in ()
|
||||
in
|
||||
try read_in () with End_of_file -> ();
|
||||
|
||||
let rec read_err () =
|
||||
let err_line = input_line stderr in
|
||||
Buffer.add_string err_buffer err_line;
|
||||
Buffer.add_char err_buffer '\n';
|
||||
read_err ()
|
||||
in
|
||||
try read_err () with
|
||||
End_of_file -> let exit_status =
|
||||
handle_exit_status (Unix.close_process_full (stdout, stdin, stderr))
|
||||
in
|
||||
{
|
||||
output = String.trim (Buffer.contents in_buffer);
|
||||
error = Buffer.contents err_buffer;
|
||||
status = exit_status;
|
||||
}
|
||||
|
||||
let format (output: output): string =
|
||||
match output with
|
||||
| { output = o; error = _; status = "Exit 0" } -> o
|
||||
| { output = ""; error = e; status = s } -> "[" ^ s ^ "]" ^ " " ^ e
|
||||
| { output = o; error = _; status = s } -> "[" ^ s ^ "]" ^ " " ^ o
|
||||
Loading…
Add table
Add a link
Reference in a new issue