Commit b155a76a authored by Joe Poirier's avatar Joe Poirier Committed by Alex Brainman

exec.LookPath() unix/windows separation

R=brainman, rsc, vcc, rsc1
CC=golang-dev
https://golang.org/cl/2068041
parent e181bf6e
...@@ -8,4 +8,21 @@ TARG=exec ...@@ -8,4 +8,21 @@ TARG=exec
GOFILES=\ GOFILES=\
exec.go\ 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 include ../../Make.pkg
...@@ -7,7 +7,6 @@ package exec ...@@ -7,7 +7,6 @@ package exec
import ( import (
"os" "os"
"strings"
) )
// Arguments to Run. // Arguments to Run.
...@@ -182,40 +181,3 @@ func (p *Cmd) Close() os.Error { ...@@ -182,40 +181,3 @@ func (p *Cmd) Close() os.Error {
} }
return err 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
}
...@@ -12,7 +12,11 @@ import ( ...@@ -12,7 +12,11 @@ import (
) )
func TestRunCat(t *testing.T) { 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) Pipe, Pipe, DevNull)
if err != nil { if err != nil {
t.Fatal("run:", err) t.Fatal("run:", err)
...@@ -32,7 +36,11 @@ func TestRunCat(t *testing.T) { ...@@ -32,7 +36,11 @@ func TestRunCat(t *testing.T) {
} }
func TestRunEcho(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) DevNull, Pipe, DevNull)
if err != nil { if err != nil {
t.Fatal("run:", err) t.Fatal("run:", err)
...@@ -50,7 +58,11 @@ func TestRunEcho(t *testing.T) { ...@@ -50,7 +58,11 @@ func TestRunEcho(t *testing.T) {
} }
func TestStderr(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) DevNull, DevNull, Pipe)
if err != nil { if err != nil {
t.Fatal("run:", err) t.Fatal("run:", err)
...@@ -67,9 +79,12 @@ func TestStderr(t *testing.T) { ...@@ -67,9 +79,12 @@ func TestStderr(t *testing.T) {
} }
} }
func TestMergeWithStdout(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) DevNull, Pipe, MergeWithStdout)
if err != nil { if err != nil {
t.Fatal("run:", err) t.Fatal("run:", err)
...@@ -91,7 +106,11 @@ func TestAddEnvVar(t *testing.T) { ...@@ -91,7 +106,11 @@ func TestAddEnvVar(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("setenv:", err) 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) DevNull, Pipe, DevNull)
if err != nil { if err != nil {
t.Fatal("run:", err) t.Fatal("run:", err)
......
// 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
}
// 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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment