blob: db326236ee8698c03e06840ff61d11dac144943d [file] [log] [blame]
Joe Poirierb155a762010-09-12 17:38:36 +10001// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package exec
6
7import (
Russ Coxc2049d22011-11-01 22:04:37 -04008 "errors"
Joe Poirierb155a762010-09-12 17:38:36 +10009 "os"
10 "strings"
11)
12
Rob Pike4e9e9252011-06-03 07:48:06 +100013// ErrNotFound is the error resulting if a path search failed to find an executable file.
Russ Coxc2049d22011-11-01 22:04:37 -040014var ErrNotFound = errors.New("executable file not found in %PATH%")
Rob Pike4e9e9252011-06-03 07:48:06 +100015
Russ Coxc2049d22011-11-01 22:04:37 -040016func chkStat(file string) error {
Joe Poirierb155a762010-09-12 17:38:36 +100017 d, err := os.Stat(file)
18 if err != nil {
Rob Pike4e9e9252011-06-03 07:48:06 +100019 return err
Joe Poirierb155a762010-09-12 17:38:36 +100020 }
Rob Pike4e9e9252011-06-03 07:48:06 +100021 if d.IsRegular() {
22 return nil
23 }
24 return os.EPERM
Joe Poirierb155a762010-09-12 17:38:36 +100025}
26
Russ Coxc2049d22011-11-01 22:04:37 -040027func findExecutable(file string, exts []string) (string, error) {
Joe Poirierb155a762010-09-12 17:38:36 +100028 if len(exts) == 0 {
29 return file, chkStat(file)
30 }
31 f := strings.ToLower(file)
32 for _, e := range exts {
33 if strings.HasSuffix(f, e) {
34 return file, chkStat(file)
35 }
36 }
37 for _, e := range exts {
Rob Pike4e9e9252011-06-03 07:48:06 +100038 if f := file + e; chkStat(f) == nil {
39 return f, nil
Joe Poirierb155a762010-09-12 17:38:36 +100040 }
41 }
Alex Brainman123549a2011-06-23 09:16:20 +100042 return ``, os.ENOENT
Joe Poirierb155a762010-09-12 17:38:36 +100043}
44
Russ Coxc2049d22011-11-01 22:04:37 -040045func LookPath(file string) (f string, err error) {
Alex Brainmanc195cc82011-06-14 11:46:05 -040046 x := os.Getenv(`PATHEXT`)
47 if x == `` {
48 x = `.COM;.EXE;.BAT;.CMD`
49 }
Joe Poirierb155a762010-09-12 17:38:36 +100050 exts := []string{}
Rob Pikeebb15662011-06-28 09:43:14 +100051 for _, e := range strings.Split(strings.ToLower(x), `;`) {
Alex Brainmanc195cc82011-06-14 11:46:05 -040052 if e == "" {
53 continue
Joe Poirierb155a762010-09-12 17:38:36 +100054 }
Alex Brainmanc195cc82011-06-14 11:46:05 -040055 if e[0] != '.' {
56 e = "." + e
57 }
58 exts = append(exts, e)
Joe Poirierb155a762010-09-12 17:38:36 +100059 }
Alex Brainman5d53aab2011-06-23 10:56:53 +100060 if strings.IndexAny(file, `:\/`) != -1 {
Rob Pike4e9e9252011-06-03 07:48:06 +100061 if f, err = findExecutable(file, exts); err == nil {
62 return
Joe Poirierb155a762010-09-12 17:38:36 +100063 }
Rob Pike4e9e9252011-06-03 07:48:06 +100064 return ``, &Error{file, err}
Joe Poirierb155a762010-09-12 17:38:36 +100065 }
66 if pathenv := os.Getenv(`PATH`); pathenv == `` {
Rob Pike4e9e9252011-06-03 07:48:06 +100067 if f, err = findExecutable(`.\`+file, exts); err == nil {
68 return
Joe Poirierb155a762010-09-12 17:38:36 +100069 }
70 } else {
Rob Pikeebb15662011-06-28 09:43:14 +100071 for _, dir := range strings.Split(pathenv, `;`) {
Rob Pike4e9e9252011-06-03 07:48:06 +100072 if f, err = findExecutable(dir+`\`+file, exts); err == nil {
73 return
Joe Poirierb155a762010-09-12 17:38:36 +100074 }
75 }
76 }
Rob Pike4e9e9252011-06-03 07:48:06 +100077 return ``, &Error{file, ErrNotFound}
Joe Poirierb155a762010-09-12 17:38:36 +100078}