]> Cypherpunks repositories - gostls13.git/commitdiff
exec.LookPath() unix/windows separation
authorJoe Poirier <jdpoirier@gmail.com>
Sun, 12 Sep 2010 07:38:36 +0000 (17:38 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Sun, 12 Sep 2010 07:38:36 +0000 (17:38 +1000)
R=brainman, rsc, vcc, rsc1
CC=golang-dev
https://golang.org/cl/2068041

src/pkg/exec/Makefile
src/pkg/exec/exec.go
src/pkg/exec/exec_test.go
src/pkg/exec/lp_unix.go [new file with mode: 0644]
src/pkg/exec/lp_windows.go [new file with mode: 0644]

index bffc1bf36105ee203cd0a4738b646c8585016a3d..6110414ac33bb33de0644e2e288a3883b8f37383 100644 (file)
@@ -8,4 +8,21 @@ TARG=exec
 GOFILES=\
        exec.go\
 
+GOFILES_freebsd=\
+       lp_unix.go\
+
+GOFILES_darwin=\
+       lp_unix.go\
+
+GOFILES_linux=\
+       lp_unix.go\
+
+GOFILES_nacl=\
+       lp_unix.go\
+
+GOFILES_windows=\
+       lp_windows.go\
+
+GOFILES+=$(GOFILES_$(GOOS))
+
 include ../../Make.pkg
index 7ae4519ab550769aefc8d86d613d77d565c85741..ba9bd2472a4b17e13951596c2032a802c407c084 100644 (file)
@@ -7,7 +7,6 @@ package exec
 
 import (
        "os"
-       "strings"
 )
 
 // Arguments to Run.
@@ -182,40 +181,3 @@ func (p *Cmd) Close() os.Error {
        }
        return err
 }
-
-func canExec(file string) bool {
-       d, err := os.Stat(file)
-       if err != nil {
-               return false
-       }
-       return d.IsRegular() && d.Permission()&0111 != 0
-}
-
-// LookPath searches for an executable binary named file
-// in the directories named by the PATH environment variable.
-// If file contains a slash, it is tried directly and the PATH is not consulted.
-//
-// TODO(rsc): Does LookPath belong in os instead?
-func LookPath(file string) (string, os.Error) {
-       // NOTE(rsc): I wish we could use the Plan 9 behavior here
-       // (only bypass the path if file begins with / or ./ or ../)
-       // but that would not match all the Unix shells.
-
-       if strings.Index(file, "/") >= 0 {
-               if canExec(file) {
-                       return file, nil
-               }
-               return "", os.ENOENT
-       }
-       pathenv := os.Getenv("PATH")
-       for _, dir := range strings.Split(pathenv, ":", -1) {
-               if dir == "" {
-                       // Unix shell semantics: path element "" means "."
-                       dir = "."
-               }
-               if canExec(dir + "/" + file) {
-                       return dir + "/" + file, nil
-               }
-       }
-       return "", os.ENOENT
-}
index 898f42582b976f93af8cca9f628a30f8261c4a2a..04f72cf833bc235ff01cf47d93b03a354e163c72 100644 (file)
@@ -12,7 +12,11 @@ import (
 )
 
 func TestRunCat(t *testing.T) {
-       cmd, err := Run("/bin/cat", []string{"cat"}, nil, "",
+       cat, err := LookPath("cat")
+       if err != nil {
+               t.Fatal("cat: ", err)
+       }
+       cmd, err := Run(cat, []string{"cat"}, nil, "",
                Pipe, Pipe, DevNull)
        if err != nil {
                t.Fatal("run:", err)
@@ -32,7 +36,11 @@ func TestRunCat(t *testing.T) {
 }
 
 func TestRunEcho(t *testing.T) {
-       cmd, err := Run("/bin/echo", []string{"echo", "hello", "world"}, nil, "",
+       echo, err := LookPath("echo")
+       if err != nil {
+               t.Fatal("echo: ", err)
+       }
+       cmd, err := Run(echo, []string{"echo", "hello", "world"}, nil, "",
                DevNull, Pipe, DevNull)
        if err != nil {
                t.Fatal("run:", err)
@@ -50,7 +58,11 @@ func TestRunEcho(t *testing.T) {
 }
 
 func TestStderr(t *testing.T) {
-       cmd, err := Run("/bin/sh", []string{"sh", "-c", "echo hello world 1>&2"}, nil, "",
+       sh, err := LookPath("sh")
+       if err != nil {
+               t.Fatal("sh: ", err)
+       }
+       cmd, err := Run(sh, []string{"sh", "-c", "echo hello world 1>&2"}, nil, "",
                DevNull, DevNull, Pipe)
        if err != nil {
                t.Fatal("run:", err)
@@ -67,9 +79,12 @@ func TestStderr(t *testing.T) {
        }
 }
 
-
 func TestMergeWithStdout(t *testing.T) {
-       cmd, err := Run("/bin/sh", []string{"sh", "-c", "echo hello world 1>&2"}, nil, "",
+       sh, err := LookPath("sh")
+       if err != nil {
+               t.Fatal("sh: ", err)
+       }
+       cmd, err := Run(sh, []string{"sh", "-c", "echo hello world 1>&2"}, nil, "",
                DevNull, Pipe, MergeWithStdout)
        if err != nil {
                t.Fatal("run:", err)
@@ -91,7 +106,11 @@ func TestAddEnvVar(t *testing.T) {
        if err != nil {
                t.Fatal("setenv:", err)
        }
-       cmd, err := Run("/bin/sh", []string{"sh", "-c", "echo $NEWVAR"}, nil, "",
+       sh, err := LookPath("sh")
+       if err != nil {
+               t.Fatal("sh: ", err)
+       }
+       cmd, err := Run(sh, []string{"sh", "-c", "echo $NEWVAR"}, nil, "",
                DevNull, Pipe, DevNull)
        if err != nil {
                t.Fatal("run:", err)
diff --git a/src/pkg/exec/lp_unix.go b/src/pkg/exec/lp_unix.go
new file mode 100644 (file)
index 0000000..10f3da1
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package exec
+
+import (
+       "os"
+       "strings"
+)
+
+func canExec(file string) bool {
+       d, err := os.Stat(file)
+       if err != nil {
+               return false
+       }
+       return d.IsRegular() && d.Permission()&0111 != 0
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the PATH environment variable.
+// If file contains a slash, it is tried directly and the PATH is not consulted.
+func LookPath(file string) (string, os.Error) {
+       // NOTE(rsc): I wish we could use the Plan 9 behavior here
+       // (only bypass the path if file begins with / or ./ or ../)
+       // but that would not match all the Unix shells.
+
+       if strings.Index(file, "/") >= 0 {
+               if canExec(file) {
+                       return file, nil
+               }
+               return "", os.ENOENT
+       }
+       pathenv := os.Getenv("PATH")
+       for _, dir := range strings.Split(pathenv, ":", -1) {
+               if dir == "" {
+                       // Unix shell semantics: path element "" means "."
+                       dir = "."
+               }
+               if canExec(dir + "/" + file) {
+                       return dir + "/" + file, nil
+               }
+       }
+       return "", os.ENOENT
+}
diff --git a/src/pkg/exec/lp_windows.go b/src/pkg/exec/lp_windows.go
new file mode 100644 (file)
index 0000000..bdf6e00
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package exec
+
+import (
+       "os"
+       "strings"
+)
+
+func chkStat(file string) bool {
+       d, err := os.Stat(file)
+       if err != nil {
+               return false
+       }
+       return d.IsRegular()
+}
+
+func canExec(file string, exts []string) (string, bool) {
+       if len(exts) == 0 {
+               return file, chkStat(file)
+       }
+       f := strings.ToLower(file)
+       for _, e := range exts {
+               if strings.HasSuffix(f, e) {
+                       return file, chkStat(file)
+               }
+       }
+       for _, e := range exts {
+               if f := file + e; chkStat(f) {
+                       return f, true
+               }
+       }
+       return ``, false
+}
+
+func LookPath(file string) (string, os.Error) {
+       exts := []string{}
+       if x := os.Getenv(`PATHEXT`); x != `` {
+               exts = strings.Split(strings.ToLower(x), `;`, -1)
+               for i, e := range exts {
+                       if e == `` || e[0] != '.' {
+                               exts[i] = `.` + e
+                       }
+               }
+       }
+       if strings.Index(file, `\`) >= 0 || strings.Index(file, `/`) >= 0 {
+               if f, ok := canExec(file, exts); ok {
+                       return f, nil
+               }
+               return ``, os.ENOENT
+       }
+       if pathenv := os.Getenv(`PATH`); pathenv == `` {
+               if f, ok := canExec(`.\`+file, exts); ok {
+                       return f, nil
+               }
+       } else {
+               for _, dir := range strings.Split(pathenv, `;`, -1) {
+                       if f, ok := canExec(dir+`\`+file, exts); ok {
+                               return f, nil
+                       }
+               }
+       }
+       return ``, os.ENOENT
+}