From 508549128d21d752cb861ac2d65bc8fc89e32555 Mon Sep 17 00:00:00 2001 From: bpc2003 Date: Mon, 26 May 2025 21:41:51 -0400 Subject: Added external commands --- cmds/cd.go | 2 +- cmds/cmds.go | 52 ------------------------------------------ cmds/cmds_test.go | 67 ------------------------------------------------------- cmds/env.go | 8 +++---- cmds/exit.go | 2 +- cmds/external.go | 31 +++++++++++++++++++++++++ cmds/test.go | 11 ++++----- global/global.go | 7 ++++++ main.go | 41 +++++++++++++++++++++++++++++++--- 9 files changed, 86 insertions(+), 135 deletions(-) delete mode 100644 cmds/cmds.go delete mode 100644 cmds/cmds_test.go create mode 100644 cmds/external.go diff --git a/cmds/cd.go b/cmds/cd.go index ec2e305..3a5e9d0 100644 --- a/cmds/cd.go +++ b/cmds/cd.go @@ -4,7 +4,7 @@ import "os" // chDir: changes the current working directory // if no directory is specifed sets it to home -func chDir(args []string) error { +func ChDir(args []string) error { var dir string if len(args) == 1 { dir, _ = os.UserHomeDir() diff --git a/cmds/cmds.go b/cmds/cmds.go deleted file mode 100644 index bc521dd..0000000 --- a/cmds/cmds.go +++ /dev/null @@ -1,52 +0,0 @@ -// cmds: handles system commands -package cmds - -import ( - "fmt" - "strings" - - "gosh/global" -) - -// Eval: evaluates a provided string into a command -// if it can't find the command or the arguments are incorrect -// returns an error -func Eval(cmd string) error { - args := strings.Split(cmd, " ") - switch args[0] { - case "cd": - if err := chDir(args); err != nil { - return err - } - break - case "export": - if err := export(args); err != nil { - return err - } - break - case "unset": - if err := unset(args); err != nil { - return err - } - break - case "set": - if len(args) > 1 { - set(args) - } else { - printEnv() - } - break - case "test", "[": - global.ReturnCode = test(args) - fmt.Println(global.ReturnCode) - break - case "exit": - if err := exit(args); err != nil { - return err - } - break - case ":": - return nil - } - return nil -} diff --git a/cmds/cmds_test.go b/cmds/cmds_test.go deleted file mode 100644 index 33d6281..0000000 --- a/cmds/cmds_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package cmds - -import ( - "os" - "testing" -) - -func TestCd(t *testing.T) { - Eval("cd /tmp") - d, _ := os.Getwd() - - if d != "/tmp" { - t.Errorf("Expected %q, got %q\n", "/tmp", d) - } -} - -func TestCdFail(t *testing.T) { - c, _ := os.Getwd() - err := Eval("cd /root") - t.Logf("%v\n", err) - - d, _ := os.Getwd() - if c != d || err == nil { - t.Errorf("Expected %q, got %q\n", c, d) - } -} - -func TestExport(t *testing.T) { - err := Eval("export TEST=true") - test := os.Getenv("TEST") - - if err != nil { - t.Errorf("%v\n", err) - } - if test != "true" { - t.Errorf("Expected %q, got %q\n", "true", test) - } -} - -func TestExportFail(t *testing.T) { - err := Eval("export TEST = 123") - if err == nil { - t.Errorf("Didn't get error\n") - } - t.Logf("%v\n", err) -} - -func TestUnset(t *testing.T) { - err := Eval("unset TEST") - test := os.Getenv("TEST") - - if err != nil { - t.Logf("%v\n", err) - } - if test != "" { - t.Errorf("Expected empty string, got %q\n", test) - } -} - -func TestExitFail(t *testing.T) { - err := Eval("exit abc") - - if err == nil { - t.Errorf("Didn't get error\n") - } - t.Logf("%v\n", err) -} diff --git a/cmds/env.go b/cmds/env.go index 5f09df6..17b220d 100644 --- a/cmds/env.go +++ b/cmds/env.go @@ -10,7 +10,7 @@ import ( ) // printEnv: prints all environment variables with shell options. -func printEnv() { +func PrintEnv() { vars := os.Environ() for i := range vars { fmt.Println(vars[i]) @@ -21,7 +21,7 @@ func printEnv() { } // set: sets the shell options -func set(args []string) { +func Set(args []string) { for i := 1; i < len(args); i++ { if i-1 >= len(global.Options) { global.Options = append(global.Options, args[i]) @@ -36,7 +36,7 @@ func set(args []string) { } // unset: unsets an environment variable -func unset(args []string) error { +func Unset(args []string) error { if len(args) == 1 || len(args) >= 3 { return errors.New("usage: unset [name]") } @@ -46,7 +46,7 @@ func unset(args []string) error { // export: exports a key-value pair to the environment // in the form of `name=value` -func export(args []string) error { +func Export(args []string) error { if len(args) == 1 || len(args) >= 3 { return errors.New("usage: export [name=value]") } diff --git a/cmds/exit.go b/cmds/exit.go index 52f082a..fc6d852 100644 --- a/cmds/exit.go +++ b/cmds/exit.go @@ -10,7 +10,7 @@ import ( // exit the shell and returns the provided status // if no status is specified returns 0 -func exit(args []string) error { +func Exit(args []string) error { status := global.ReturnCode if len(args) > 1 { var err error diff --git a/cmds/external.go b/cmds/external.go new file mode 100644 index 0000000..da24291 --- /dev/null +++ b/cmds/external.go @@ -0,0 +1,31 @@ +package cmds + +import ( + "fmt" + "os" + "os/exec" + "path" + + "gosh/global" +) + +func External(args []string) { + cmd := "" + found := false + for i := range global.Paths { + cmd = path.Join(global.Paths[i], args[0]) + if _, err := os.Stat(cmd); err == nil { + found = true + break + } + } + if found { + cmd := exec.Command(cmd, args[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + cmd.Run() + return + } + fmt.Fprintf(os.Stderr, "%s: Command not found\n", args[0]) +} diff --git a/cmds/test.go b/cmds/test.go index 59989d3..f952384 100644 --- a/cmds/test.go +++ b/cmds/test.go @@ -8,7 +8,7 @@ import ( "syscall" ) -func test(args []string) int { +func Test(args []string) int { if len(args) <= 2 { return 1 } @@ -16,6 +16,9 @@ func test(args []string) int { if strings.HasPrefix(args[1], "-") { return genTest(args[1:]) } else { + if len(args) != 4 { + return 1 + } _, err := strconv.Atoi(args[1]) if err != nil { return testString(args[1:]) @@ -26,9 +29,6 @@ func test(args []string) int { } func testString(args []string) int { - if len(args) != 3 { - return 1 - } sTests := map[string]func() bool{ "=": func() bool { return args[0] == args[2] }, "!=": func() bool { return args[0] != args[2] }, @@ -42,9 +42,6 @@ func testString(args []string) int { } func testNumber(args []string) int { - if len(args) != 3 { - return 1 - } a, _ := strconv.Atoi(args[0]) b, err := strconv.Atoi(args[2]) if err != nil { diff --git a/global/global.go b/global/global.go index f84a340..708f05a 100644 --- a/global/global.go +++ b/global/global.go @@ -1,9 +1,16 @@ package global +import ( + "os" + "strings" +) + var Options []string var ReturnCode int +var Paths []string func init() { Options = make([]string, 0) ReturnCode = 0 + Paths = strings.Split(os.Getenv("PATH"), ":") } diff --git a/main.go b/main.go index 52c7ba0..5334796 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "strings" "gosh/cmds" + "gosh/global" ) func main() { @@ -22,9 +23,43 @@ func main() { } cmd = strings.TrimSuffix(cmd, "\n") - err = cmds.Eval(cmd) - if err != nil { - fmt.Fprintln(os.Stderr, err) + args := strings.Split(cmd, " ") + switch (args[0]) { + case "cd": + if err := cmds.ChDir(args); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + } + break + case "export": + if err := cmds.Export(args); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + } + break + case "unset": + if err := cmds.Unset(args); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + } + break + case "set": + if len(args) == 1 { + cmds.PrintEnv() + } else { + cmds.Set(args) + } + break + case "test", "[": + global.ReturnCode = cmds.Test(args) + break + case ":": + break + case "exit": + if err := cmds.Exit(args); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + } + break + default: + cmds.External(args) + break } } } -- cgit v1.2.3