mirror of
https://github.com/golang/go
synced 2024-11-21 20:54:45 -07:00
exec.LookPath() unix/windows separation
R=brainman, rsc, vcc, rsc1 CC=golang-dev https://golang.org/cl/2068041
This commit is contained in:
parent
e181bf6e2f
commit
b155a76a40
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
45
src/pkg/exec/lp_unix.go
Normal file
45
src/pkg/exec/lp_unix.go
Normal file
@ -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
|
||||
}
|
66
src/pkg/exec/lp_windows.go
Normal file
66
src/pkg/exec/lp_windows.go
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user