|
|
|
@ -20,6 +20,7 @@ import (
|
|
|
|
|
"os/exec"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"os/user"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"runtime"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
@ -915,6 +916,14 @@ func BabysitProc(ctx context.Context, args []string, logf logger.Logf) {
|
|
|
|
|
startTime := time.Now()
|
|
|
|
|
log.Printf("exec: %#v %v", executable, args)
|
|
|
|
|
cmd := exec.Command(executable, args...)
|
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
|
extraEnv, err := loadExtraEnv()
|
|
|
|
|
if err != nil {
|
|
|
|
|
logf("errors loading extra env file; ignoring: %v", err)
|
|
|
|
|
} else {
|
|
|
|
|
cmd.Env = append(os.Environ(), extraEnv...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a pipe object to use as the subproc's stdin.
|
|
|
|
|
// When the writer goes away, the reader gets EOF.
|
|
|
|
@ -1184,3 +1193,47 @@ func findTrueNASTaildropDir(name string) (dir string, err error) {
|
|
|
|
|
}
|
|
|
|
|
return "", fmt.Errorf("shared folder %q not found", name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func loadExtraEnv() (env []string, err error) {
|
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
name := filepath.Join(os.Getenv("ProgramData"), "Tailscale", "tailscaled-env.txt")
|
|
|
|
|
contents, err := os.ReadFile(name)
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
for _, line := range strings.Split(string(contents), "\n") {
|
|
|
|
|
line = strings.TrimSpace(line)
|
|
|
|
|
if line == "" || line[0] == '#' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
k, v, ok := stringsCut(line, "=")
|
|
|
|
|
if !ok || k == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if strings.HasPrefix(v, `"`) {
|
|
|
|
|
var err error
|
|
|
|
|
v, err = strconv.Unquote(v)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid value in line %q: %v", line, err)
|
|
|
|
|
}
|
|
|
|
|
env = append(env, k+"="+v)
|
|
|
|
|
} else {
|
|
|
|
|
env = append(env, line)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return env, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// stringsCut is Go 1.18's strings.Cut.
|
|
|
|
|
// TODO(bradfitz): delete this when we depend on Go 1.18.
|
|
|
|
|
func stringsCut(s, sep string) (before, after string, found bool) {
|
|
|
|
|
if i := strings.Index(s, sep); i >= 0 {
|
|
|
|
|
return s[:i], s[i+len(sep):], true
|
|
|
|
|
}
|
|
|
|
|
return s, "", false
|
|
|
|
|
}
|
|
|
|
|