github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/uniter/runner/args.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package runner 5 6 import ( 7 "fmt" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 13 "github.com/juju/juju/version" 14 ) 15 16 var windowsSuffixOrder = []string{ 17 ".ps1", 18 ".cmd", 19 ".bat", 20 ".exe", 21 } 22 23 func lookPath(hook string) (string, error) { 24 hookFile, err := exec.LookPath(hook) 25 if err != nil { 26 if ee, ok := err.(*exec.Error); ok && os.IsNotExist(ee.Err) { 27 return "", &missingHookError{hook} 28 } 29 return "", err 30 } 31 return hookFile, nil 32 } 33 34 // searchHook will search, in order, hooks suffixed with extensions 35 // in windowsSuffixOrder. As windows cares about extensions to determine 36 // how to execute a file, we will allow several suffixes, with powershell 37 // being default. 38 func searchHook(charmDir, hook string) (string, error) { 39 hookFile := filepath.Join(charmDir, hook) 40 if version.Current.OS != version.Windows { 41 // we are not running on windows, 42 // there is no need to look for suffixed hooks 43 return lookPath(hookFile) 44 } 45 for _, suffix := range windowsSuffixOrder { 46 file := fmt.Sprintf("%s%s", hookFile, suffix) 47 foundHook, err := lookPath(file) 48 if err != nil { 49 if IsMissingHookError(err) { 50 // look for next suffix 51 continue 52 } 53 return "", err 54 } 55 return foundHook, nil 56 } 57 return "", &missingHookError{hook} 58 } 59 60 // hookCommand constructs an appropriate command to be passed to 61 // exec.Command(). The exec package uses cmd.exe as default on windows. 62 // cmd.exe does not know how to execute ps1 files by default, and 63 // powershell needs a few flags to allow execution (-ExecutionPolicy) 64 // and propagate error levels (-File). .cmd and .bat files can be run 65 // directly. 66 func hookCommand(hook string) []string { 67 if version.Current.OS != version.Windows { 68 // we are not running on windows, 69 // just return the hook name 70 return []string{hook} 71 } 72 if strings.HasSuffix(hook, ".ps1") { 73 return []string{ 74 "powershell.exe", 75 "-NonInteractive", 76 "-ExecutionPolicy", 77 "RemoteSigned", 78 "-File", 79 hook, 80 } 81 } 82 return []string{hook} 83 }