open Unix open List open Str (* Fork new processes. *) let shell_exec strs = match strs with | [] -> print_endline "Error: Bad Input" | cmd :: _ -> let cmd_args = Array.of_list strs in let pid = fork () in match pid with | 0 -> begin try execvp cmd cmd_args with | Unix_error (ENOENT, cmd, cmd_args) -> print_endline "No such program." | Unix_error (ENOEXEC,_,_) -> print_endline "Not an exec." | Unix_error (_,_,_) -> print_endline "Something is wrong!" end; exit 0 | _ -> ignore (wait ()) let shell_cd strs = if (strs = []) then print_string "" else try chdir (hd strs) with _ -> print_endline "Error changing directory." (* Dispatch loop *) let input_dispatch pstr = if (pstr <> []) then begin let cmd = hd pstr in let cmd_args = tl pstr in match cmd with | "cd" -> shell_cd cmd_args | "pid" -> print_endline (string_of_int (getpid ())) | "gc-stat" -> Gc.print_stat Pervasives.stdout | "exit" -> exit 0 | _ -> shell_exec pstr end else print_string "" (* Parse the users input string, return a list of strings. *) let parse_string str = let pstr = split (regexp " +") str in pstr let rec shell_loop () = begin print_string (getcwd ()); print_string " % "; input_dispatch (parse_string (read_line ())); shell_loop () end let main () = if Array.length Sys.argv < 2 then begin print_string "OShell v1.0a on OCaml "; print_endline Sys.ocaml_version; shell_loop () end else let lstr = Array.to_list Sys.argv in (* Get rid of Sys.argv(0), the program name. *) let pstr = tl lstr in input_dispatch pstr let _ = main ()