Last active
August 24, 2019 10:49
-
-
Save aprell/d36f73e756b683c2e92a6b84aa4b380d to your computer and use it in GitHub Desktop.
OCaml port of https://brennan.io/2015/01/16/write-a-shell-in-c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| open Unix | |
| let lsh_builtins = ["cd"; "help"; "exit"] | |
| let print_error msg = | |
| prerr_string "lsh: "; | |
| prerr_endline msg | |
| let lsh_cd args = | |
| assert (args.(0) = "cd"); | |
| if Array.length args < 2 then | |
| print_error "Expected argument to \"cd\"" | |
| else | |
| try chdir args.(1) | |
| with Unix_error (e, _, _) -> | |
| print_error (error_message e) | |
| let lsh_help args = | |
| print_endline "Stephen Brennan's LSH"; | |
| print_endline "Type program names and arguments, and hit enter."; | |
| print_endline "The following are built in:"; | |
| List.iter (Printf.printf " %s\n") lsh_builtins; | |
| print_endline "Use the man command for information on other programs." | |
| let lsh_exit args = | |
| raise Exit | |
| let lsh_builtin_cmds = | |
| List.map2 | |
| (fun a b -> (a, b)) | |
| lsh_builtins | |
| [lsh_cd; lsh_help; lsh_exit] | |
| let lookup cmd = | |
| try Some (List.assoc cmd lsh_builtin_cmds) | |
| with Not_found -> None | |
| let lsh_launch args = | |
| match fork () with | |
| | 0 -> (* child process *) | |
| begin try execvp args.(0) args | |
| with Unix_error (e, _, _) -> | |
| print_error (error_message e) | |
| end; | |
| exit 1 | |
| | pid -> (* parent process *) | |
| let wpid, _ (* status *) = wait () in | |
| assert (pid = wpid) | |
| let lsh_execute args = | |
| if Array.length args > 0 then | |
| match lookup args.(0) with | |
| | Some builtin -> builtin args | |
| | None -> lsh_launch args | |
| let lsh_read_line = read_line | |
| let lsh_split_line = Str.split (Str.regexp "[ \t\r\n]+") | |
| let lsh_loop () = | |
| try | |
| while true do | |
| print_string "> "; | |
| lsh_read_line () | |
| |> lsh_split_line | |
| |> Array.of_list | |
| |> lsh_execute | |
| done | |
| with | |
| | End_of_file -> () | |
| | Exit -> print_endline "Bye" | |
| let () = | |
| lsh_loop () |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Related: Writing a simple *nix shell