summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/cd.go2
-rw-r--r--cmds/cmds.go52
-rw-r--r--cmds/cmds_test.go67
-rw-r--r--cmds/env.go8
-rw-r--r--cmds/exit.go2
-rw-r--r--cmds/external.go31
-rw-r--r--cmds/test.go11
-rw-r--r--global/global.go7
-rw-r--r--main.go41
9 files changed, 86 insertions, 135 deletions
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
}
}
}