package main import ( "bufio" "fmt" "os" "os/exec" "strings" "unicode" ) func main() { // Load the configuration file, if any // Run command loop myshell_loop() // Perform any shutdown/cleanup } func myshell_loop() { for { // Read command fmt.Printf("myshell> ") line := read_line() // Parse command args := split_line(line) // Execute command output, err := execute(args) if err != nil { fmt.Println("error during exec command:", err) } else { fmt.Printf(string(output)) } } // Loop back to read command } func read_line() string { // Read the command line reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\n') if err != nil { fmt.Println("Error reading command line: ", err) } // Remove the newline character input = strings.TrimSuffix(input, "\r\n") input = strings.TrimSuffix(input, "\n") return input } // Split the line into arguments func split_line(line string) []string { fieldSeparator := func(c rune) bool { return unicode.IsSpace(c) || c == '\a' } args := strings.FieldsFunc(line, fieldSeparator) return args } var builtin_cmds = map[string]func([]string) ([]byte, error){ "cd": myshell_cd, "exit": myshell_exit, } // Execute the command func execute(args []string) ([]byte, error) { // Check for builtin commands if cmd, ok := builtin_cmds[args[0]]; ok { return cmd(args) } cmd := exec.Command("sh", "-c", strings.Join(args, " ")) output, err := cmd.CombinedOutput() return output, err } func myshell_cd(args []string) ([]byte, error) { if len(args) < 2 { return nil, fmt.Errorf("cd: missing argument") } err := os.Chdir(args[1]) return nil, err } func myshell_exit(args []string) ([]byte, error) { os.Exit(0) return nil, nil }