1 // Copyright 2009 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 5 // Package exec runs external commands. It wraps os.StartProcess to make it 6 // easier to remap stdin and stdout, connect I/O with pipes, and do other 7 // adjustments. 8 // 9 // Unlike the "system" library call from C and other languages, the 10 // os/exec package intentionally does not invoke the system shell and 11 // does not expand any glob patterns or handle other expansions, 12 // pipelines, or redirections typically done by shells. The package 13 // behaves more like C's "exec" family of functions. To expand glob 14 // patterns, either call the shell directly, taking care to escape any 15 // dangerous input, or use the path/filepath package's Glob function. 16 // To expand environment variables, use package os's ExpandEnv. 17 // 18 // Note that the examples in this package assume a Unix system. 19 // They may not run on Windows, and they do not run in the Go Playground 20 // used by golang.org and godoc.org. 21 // 22 // # Executables in the current directory 23 // 24 // The functions Command and LookPath look for a program 25 // in the directories listed in the current path, following the 26 // conventions of the host operating system. 27 // Operating systems have for decades included the current 28 // directory in this search, sometimes implicitly and sometimes 29 // configured explicitly that way by default. 30 // Modern practice is that including the current directory 31 // is usually unexpected and often leads to security problems. 32 // 33 // To avoid those security problems, as of Go 1.19, this package will not resolve a program 34 // using an implicit or explicit path entry relative to the current directory. 35 // That is, if you run exec.LookPath("go"), it will not successfully return 36 // ./go on Unix nor .\go.exe on Windows, no matter how the path is configured. 37 // Instead, if the usual path algorithms would result in that answer, 38 // these functions return an error err satisfying errors.Is(err, ErrDot). 39 // 40 // For example, consider these two program snippets: 41 // 42 // path, err := exec.LookPath("prog") 43 // if err != nil { 44 // log.Fatal(err) 45 // } 46 // use(path) 47 // 48 // and 49 // 50 // cmd := exec.Command("prog") 51 // if err := cmd.Run(); err != nil { 52 // log.Fatal(err) 53 // } 54 // 55 // These will not find and run ./prog or .\prog.exe, 56 // no matter how the current path is configured. 57 // 58 // Code that always wants to run a program from the current directory 59 // can be rewritten to say "./prog" instead of "prog". 60 // 61 // Code that insists on including results from relative path entries 62 // can instead override the error using an errors.Is check: 63 // 64 // path, err := exec.LookPath("prog") 65 // if errors.Is(err, exec.ErrDot) { 66 // err = nil 67 // } 68 // if err != nil { 69 // log.Fatal(err) 70 // } 71 // use(path) 72 // 73 // and 74 // 75 // cmd := exec.Command("prog") 76 // if errors.Is(cmd.Err, exec.ErrDot) { 77 // cmd.Err = nil 78 // } 79 // if err := cmd.Run(); err != nil { 80 // log.Fatal(err) 81 // } 82 // 83 // Setting the environment variable GODEBUG=execerrdot=0 84 // disables generation of ErrDot entirely, temporarily restoring the pre-Go 1.19 85 // behavior for programs that are unable to apply more targeted fixes. 86 // A future version of Go may remove support for this variable. 87 // 88 // Before adding such overrides, make sure you understand the 89 // security implications of doing so. 90 // See https://go.dev/blog/path-security for more information. 91 package exec 92 93 import ( 94 "bytes" 95 "context" 96 "errors" 97 "internal/syscall/execenv" 98 "io" 99 "os" 100 "path/filepath" 101 "runtime" 102 "strconv" 103 "strings" 104 "sync" 105 "syscall" 106 ) 107 108 // Error is returned by LookPath when it fails to classify a file as an 109 // executable. 110 type Error struct { 111 // Name is the file name for which the error occurred. 112 Name string 113 // Err is the underlying error. 114 Err error 115 } 116 117 func (e *Error) Error() string { 118 return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error() 119 } 120 121 func (e *Error) Unwrap() error { return e.Err } 122 123 // wrappedError wraps an error without relying on fmt.Errorf. 124 type wrappedError struct { 125 prefix string 126 err error 127 } 128 129 func (w wrappedError) Error() string { 130 return w.prefix + ": " + w.err.Error() 131 } 132 133 func (w wrappedError) Unwrap() error { 134 return w.err 135 } 136 137 // Cmd represents an external command being prepared or run. 138 // 139 // A Cmd cannot be reused after calling its Run, Output or CombinedOutput 140 // methods. 141 type Cmd struct { 142 // Path is the path of the command to run. 143 // 144 // This is the only field that must be set to a non-zero 145 // value. If Path is relative, it is evaluated relative 146 // to Dir. 147 Path string 148 149 // Args holds command line arguments, including the command as Args[0]. 150 // If the Args field is empty or nil, Run uses {Path}. 151 // 152 // In typical use, both Path and Args are set by calling Command. 153 Args []string 154 155 // Env specifies the environment of the process. 156 // Each entry is of the form "key=value". 157 // If Env is nil, the new process uses the current process's 158 // environment. 159 // If Env contains duplicate environment keys, only the last 160 // value in the slice for each duplicate key is used. 161 // As a special case on Windows, SYSTEMROOT is always added if 162 // missing and not explicitly set to the empty string. 163 Env []string 164 165 // Dir specifies the working directory of the command. 166 // If Dir is the empty string, Run runs the command in the 167 // calling process's current directory. 168 Dir string 169 170 // Stdin specifies the process's standard input. 171 // 172 // If Stdin is nil, the process reads from the null device (os.DevNull). 173 // 174 // If Stdin is an *os.File, the process's standard input is connected 175 // directly to that file. 176 // 177 // Otherwise, during the execution of the command a separate 178 // goroutine reads from Stdin and delivers that data to the command 179 // over a pipe. In this case, Wait does not complete until the goroutine 180 // stops copying, either because it has reached the end of Stdin 181 // (EOF or a read error) or because writing to the pipe returned an error. 182 Stdin io.Reader 183 184 // Stdout and Stderr specify the process's standard output and error. 185 // 186 // If either is nil, Run connects the corresponding file descriptor 187 // to the null device (os.DevNull). 188 // 189 // If either is an *os.File, the corresponding output from the process 190 // is connected directly to that file. 191 // 192 // Otherwise, during the execution of the command a separate goroutine 193 // reads from the process over a pipe and delivers that data to the 194 // corresponding Writer. In this case, Wait does not complete until the 195 // goroutine reaches EOF or encounters an error. 196 // 197 // If Stdout and Stderr are the same writer, and have a type that can 198 // be compared with ==, at most one goroutine at a time will call Write. 199 Stdout io.Writer 200 Stderr io.Writer 201 202 // ExtraFiles specifies additional open files to be inherited by the 203 // new process. It does not include standard input, standard output, or 204 // standard error. If non-nil, entry i becomes file descriptor 3+i. 205 // 206 // ExtraFiles is not supported on Windows. 207 ExtraFiles []*os.File 208 209 // SysProcAttr holds optional, operating system-specific attributes. 210 // Run passes it to os.StartProcess as the os.ProcAttr's Sys field. 211 SysProcAttr *syscall.SysProcAttr 212 213 // Process is the underlying process, once started. 214 Process *os.Process 215 216 // ProcessState contains information about an exited process, 217 // available after a call to Wait or Run. 218 ProcessState *os.ProcessState 219 220 ctx context.Context // nil means none 221 Err error // LookPath error, if any. 222 childFiles []*os.File 223 closeAfterStart []io.Closer 224 closeAfterWait []io.Closer 225 goroutine []func() error 226 goroutineErrs <-chan error // one receive per goroutine 227 ctxErr <-chan error // if non nil, receives the error from watchCtx exactly once 228 229 // For a security release long ago, we created x/sys/execabs, 230 // which manipulated the unexported lookPathErr error field 231 // in this struct. For Go 1.19 we exported the field as Err error, 232 // above, but we have to keep lookPathErr around for use by 233 // old programs building against new toolchains. 234 // The String and Start methods look for an error in lookPathErr 235 // in preference to Err, to preserve the errors that execabs sets. 236 // 237 // In general we don't guarantee misuse of reflect like this, 238 // but the misuse of reflect was by us, the best of various bad 239 // options to fix the security problem, and people depend on 240 // those old copies of execabs continuing to work. 241 // The result is that we have to leave this variable around for the 242 // rest of time, a compatibility scar. 243 // 244 // See https://go.dev/blog/path-security 245 // and https://go.dev/issue/43724 for more context. 246 lookPathErr error 247 } 248 249 // Command returns the Cmd struct to execute the named program with 250 // the given arguments. 251 // 252 // It sets only the Path and Args in the returned structure. 253 // 254 // If name contains no path separators, Command uses LookPath to 255 // resolve name to a complete path if possible. Otherwise it uses name 256 // directly as Path. 257 // 258 // The returned Cmd's Args field is constructed from the command name 259 // followed by the elements of arg, so arg should not include the 260 // command name itself. For example, Command("echo", "hello"). 261 // Args[0] is always name, not the possibly resolved Path. 262 // 263 // On Windows, processes receive the whole command line as a single string 264 // and do their own parsing. Command combines and quotes Args into a command 265 // line string with an algorithm compatible with applications using 266 // CommandLineToArgvW (which is the most common way). Notable exceptions are 267 // msiexec.exe and cmd.exe (and thus, all batch files), which have a different 268 // unquoting algorithm. In these or other similar cases, you can do the 269 // quoting yourself and provide the full command line in SysProcAttr.CmdLine, 270 // leaving Args empty. 271 func Command(name string, arg ...string) *Cmd { 272 cmd := &Cmd{ 273 Path: name, 274 Args: append([]string{name}, arg...), 275 } 276 if filepath.Base(name) == name { 277 lp, err := LookPath(name) 278 if lp != "" { 279 // Update cmd.Path even if err is non-nil. 280 // If err is ErrDot (especially on Windows), lp may include a resolved 281 // extension (like .exe or .bat) that should be preserved. 282 cmd.Path = lp 283 } 284 if err != nil { 285 cmd.Err = err 286 } 287 } 288 return cmd 289 } 290 291 // CommandContext is like Command but includes a context. 292 // 293 // The provided context is used to kill the process (by calling 294 // os.Process.Kill) if the context becomes done before the command 295 // completes on its own. 296 func CommandContext(ctx context.Context, name string, arg ...string) *Cmd { 297 if ctx == nil { 298 panic("nil Context") 299 } 300 cmd := Command(name, arg...) 301 cmd.ctx = ctx 302 return cmd 303 } 304 305 // String returns a human-readable description of c. 306 // It is intended only for debugging. 307 // In particular, it is not suitable for use as input to a shell. 308 // The output of String may vary across Go releases. 309 func (c *Cmd) String() string { 310 if c.Err != nil || c.lookPathErr != nil { 311 // failed to resolve path; report the original requested path (plus args) 312 return strings.Join(c.Args, " ") 313 } 314 // report the exact executable path (plus args) 315 b := new(strings.Builder) 316 b.WriteString(c.Path) 317 for _, a := range c.Args[1:] { 318 b.WriteByte(' ') 319 b.WriteString(a) 320 } 321 return b.String() 322 } 323 324 // interfaceEqual protects against panics from doing equality tests on 325 // two interfaces with non-comparable underlying types. 326 func interfaceEqual(a, b any) bool { 327 defer func() { 328 recover() 329 }() 330 return a == b 331 } 332 333 func (c *Cmd) argv() []string { 334 if len(c.Args) > 0 { 335 return c.Args 336 } 337 return []string{c.Path} 338 } 339 340 func (c *Cmd) stdin() (f *os.File, err error) { 341 if c.Stdin == nil { 342 f, err = os.Open(os.DevNull) 343 if err != nil { 344 return 345 } 346 c.closeAfterStart = append(c.closeAfterStart, f) 347 return 348 } 349 350 if f, ok := c.Stdin.(*os.File); ok { 351 return f, nil 352 } 353 354 pr, pw, err := os.Pipe() 355 if err != nil { 356 return 357 } 358 359 c.closeAfterStart = append(c.closeAfterStart, pr) 360 c.closeAfterWait = append(c.closeAfterWait, pw) 361 c.goroutine = append(c.goroutine, func() error { 362 _, err := io.Copy(pw, c.Stdin) 363 if skipStdinCopyError(err) { 364 err = nil 365 } 366 if err1 := pw.Close(); err == nil { 367 err = err1 368 } 369 return err 370 }) 371 return pr, nil 372 } 373 374 func (c *Cmd) stdout() (f *os.File, err error) { 375 return c.writerDescriptor(c.Stdout) 376 } 377 378 func (c *Cmd) stderr() (f *os.File, err error) { 379 if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) { 380 return c.childFiles[1], nil 381 } 382 return c.writerDescriptor(c.Stderr) 383 } 384 385 func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) { 386 if w == nil { 387 f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0) 388 if err != nil { 389 return 390 } 391 c.closeAfterStart = append(c.closeAfterStart, f) 392 return 393 } 394 395 if f, ok := w.(*os.File); ok { 396 return f, nil 397 } 398 399 pr, pw, err := os.Pipe() 400 if err != nil { 401 return 402 } 403 404 c.closeAfterStart = append(c.closeAfterStart, pw) 405 c.closeAfterWait = append(c.closeAfterWait, pr) 406 c.goroutine = append(c.goroutine, func() error { 407 _, err := io.Copy(w, pr) 408 pr.Close() // in case io.Copy stopped due to write error 409 return err 410 }) 411 return pw, nil 412 } 413 414 func (c *Cmd) closeDescriptors(closers []io.Closer) { 415 for _, fd := range closers { 416 fd.Close() 417 } 418 } 419 420 // Run starts the specified command and waits for it to complete. 421 // 422 // The returned error is nil if the command runs, has no problems 423 // copying stdin, stdout, and stderr, and exits with a zero exit 424 // status. 425 // 426 // If the command starts but does not complete successfully, the error is of 427 // type *ExitError. Other error types may be returned for other situations. 428 // 429 // If the calling goroutine has locked the operating system thread 430 // with runtime.LockOSThread and modified any inheritable OS-level 431 // thread state (for example, Linux or Plan 9 name spaces), the new 432 // process will inherit the caller's thread state. 433 func (c *Cmd) Run() error { 434 if err := c.Start(); err != nil { 435 return err 436 } 437 return c.Wait() 438 } 439 440 // lookExtensions finds windows executable by its dir and path. 441 // It uses LookPath to try appropriate extensions. 442 // lookExtensions does not search PATH, instead it converts `prog` into `.\prog`. 443 func lookExtensions(path, dir string) (string, error) { 444 if filepath.Base(path) == path { 445 path = "." + string(filepath.Separator) + path 446 } 447 if dir == "" { 448 return LookPath(path) 449 } 450 if filepath.VolumeName(path) != "" { 451 return LookPath(path) 452 } 453 if len(path) > 1 && os.IsPathSeparator(path[0]) { 454 return LookPath(path) 455 } 456 dirandpath := filepath.Join(dir, path) 457 // We assume that LookPath will only add file extension. 458 lp, err := LookPath(dirandpath) 459 if err != nil { 460 return "", err 461 } 462 ext := strings.TrimPrefix(lp, dirandpath) 463 return path + ext, nil 464 } 465 466 // Start starts the specified command but does not wait for it to complete. 467 // 468 // If Start returns successfully, the c.Process field will be set. 469 // 470 // After a successful call to Start the Wait method must be called in 471 // order to release associated system resources. 472 func (c *Cmd) Start() error { 473 if c.Path == "" && c.Err == nil && c.lookPathErr == nil { 474 c.Err = errors.New("exec: no command") 475 } 476 if c.Err != nil || c.lookPathErr != nil { 477 c.closeDescriptors(c.closeAfterStart) 478 c.closeDescriptors(c.closeAfterWait) 479 if c.lookPathErr != nil { 480 return c.lookPathErr 481 } 482 return c.Err 483 } 484 if runtime.GOOS == "windows" { 485 lp, err := lookExtensions(c.Path, c.Dir) 486 if err != nil { 487 c.closeDescriptors(c.closeAfterStart) 488 c.closeDescriptors(c.closeAfterWait) 489 return err 490 } 491 c.Path = lp 492 } 493 if c.Process != nil { 494 return errors.New("exec: already started") 495 } 496 if c.ctx != nil { 497 select { 498 case <-c.ctx.Done(): 499 c.closeDescriptors(c.closeAfterStart) 500 c.closeDescriptors(c.closeAfterWait) 501 return c.ctx.Err() 502 default: 503 } 504 } 505 506 c.childFiles = make([]*os.File, 0, 3+len(c.ExtraFiles)) 507 type F func(*Cmd) (*os.File, error) 508 for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { 509 fd, err := setupFd(c) 510 if err != nil { 511 c.closeDescriptors(c.closeAfterStart) 512 c.closeDescriptors(c.closeAfterWait) 513 return err 514 } 515 c.childFiles = append(c.childFiles, fd) 516 } 517 c.childFiles = append(c.childFiles, c.ExtraFiles...) 518 519 env, err := c.environ() 520 if err != nil { 521 return err 522 } 523 524 c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ 525 Dir: c.Dir, 526 Files: c.childFiles, 527 Env: env, 528 Sys: c.SysProcAttr, 529 }) 530 if err != nil { 531 c.closeDescriptors(c.closeAfterStart) 532 c.closeDescriptors(c.closeAfterWait) 533 return err 534 } 535 536 c.closeDescriptors(c.closeAfterStart) 537 538 // Don't allocate the goroutineErrs channel unless there are goroutines to fire. 539 if len(c.goroutine) > 0 { 540 errc := make(chan error, len(c.goroutine)) 541 c.goroutineErrs = errc 542 for _, fn := range c.goroutine { 543 go func(fn func() error) { 544 errc <- fn() 545 }(fn) 546 } 547 } 548 549 c.ctxErr = c.watchCtx() 550 551 return nil 552 } 553 554 // An ExitError reports an unsuccessful exit by a command. 555 type ExitError struct { 556 *os.ProcessState 557 558 // Stderr holds a subset of the standard error output from the 559 // Cmd.Output method if standard error was not otherwise being 560 // collected. 561 // 562 // If the error output is long, Stderr may contain only a prefix 563 // and suffix of the output, with the middle replaced with 564 // text about the number of omitted bytes. 565 // 566 // Stderr is provided for debugging, for inclusion in error messages. 567 // Users with other needs should redirect Cmd.Stderr as needed. 568 Stderr []byte 569 } 570 571 func (e *ExitError) Error() string { 572 return e.ProcessState.String() 573 } 574 575 // Wait waits for the command to exit and waits for any copying to 576 // stdin or copying from stdout or stderr to complete. 577 // 578 // The command must have been started by Start. 579 // 580 // The returned error is nil if the command runs, has no problems 581 // copying stdin, stdout, and stderr, and exits with a zero exit 582 // status. 583 // 584 // If the command fails to run or doesn't complete successfully, the 585 // error is of type *ExitError. Other error types may be 586 // returned for I/O problems. 587 // 588 // If any of c.Stdin, c.Stdout or c.Stderr are not an *os.File, Wait also waits 589 // for the respective I/O loop copying to or from the process to complete. 590 // 591 // Wait releases any resources associated with the Cmd. 592 func (c *Cmd) Wait() error { 593 if c.Process == nil { 594 return errors.New("exec: not started") 595 } 596 if c.ProcessState != nil { 597 return errors.New("exec: Wait was already called") 598 } 599 state, err := c.Process.Wait() 600 if err == nil && !state.Success() { 601 err = &ExitError{ProcessState: state} 602 } 603 c.ProcessState = state 604 605 // Wait for the pipe-copying goroutines to complete. 606 var copyError error 607 for range c.goroutine { 608 if err := <-c.goroutineErrs; err != nil && copyError == nil { 609 copyError = err 610 } 611 } 612 c.goroutine = nil // Allow the goroutines' closures to be GC'd. 613 614 if c.ctxErr != nil { 615 interruptErr := <-c.ctxErr 616 // If c.Process.Wait returned an error, prefer that. 617 // Otherwise, report any error from the interrupt goroutine. 618 if interruptErr != nil && err == nil { 619 err = interruptErr 620 } 621 } 622 // Report errors from the copying goroutines only if the program otherwise 623 // exited normally on its own. Otherwise, the copying error may be due to the 624 // abnormal termination. 625 if err == nil { 626 err = copyError 627 } 628 629 c.closeDescriptors(c.closeAfterWait) 630 c.closeAfterWait = nil 631 632 return err 633 } 634 635 // watchCtx conditionally starts a goroutine that waits until either c.ctx is 636 // done or c.Process.Wait has completed (called from Wait). 637 // If c.ctx is done first, the goroutine terminates c.Process. 638 // 639 // If a goroutine was started, watchCtx returns a channel on which its result 640 // must be received. 641 func (c *Cmd) watchCtx() <-chan error { 642 if c.ctx == nil { 643 return nil 644 } 645 646 errc := make(chan error) 647 go func() { 648 select { 649 case errc <- nil: 650 return 651 case <-c.ctx.Done(): 652 } 653 654 var err error 655 if killErr := c.Process.Kill(); killErr == nil { 656 // We appear to have successfully delivered a kill signal, so any 657 // program behavior from this point may be due to ctx. 658 err = c.ctx.Err() 659 } else if !errors.Is(killErr, os.ErrProcessDone) { 660 err = wrappedError{ 661 prefix: "exec: error sending signal to Cmd", 662 err: killErr, 663 } 664 } 665 errc <- err 666 }() 667 668 return errc 669 } 670 671 // Output runs the command and returns its standard output. 672 // Any returned error will usually be of type *ExitError. 673 // If c.Stderr was nil, Output populates ExitError.Stderr. 674 func (c *Cmd) Output() ([]byte, error) { 675 if c.Stdout != nil { 676 return nil, errors.New("exec: Stdout already set") 677 } 678 var stdout bytes.Buffer 679 c.Stdout = &stdout 680 681 captureErr := c.Stderr == nil 682 if captureErr { 683 c.Stderr = &prefixSuffixSaver{N: 32 << 10} 684 } 685 686 err := c.Run() 687 if err != nil && captureErr { 688 if ee, ok := err.(*ExitError); ok { 689 ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes() 690 } 691 } 692 return stdout.Bytes(), err 693 } 694 695 // CombinedOutput runs the command and returns its combined standard 696 // output and standard error. 697 func (c *Cmd) CombinedOutput() ([]byte, error) { 698 if c.Stdout != nil { 699 return nil, errors.New("exec: Stdout already set") 700 } 701 if c.Stderr != nil { 702 return nil, errors.New("exec: Stderr already set") 703 } 704 var b bytes.Buffer 705 c.Stdout = &b 706 c.Stderr = &b 707 err := c.Run() 708 return b.Bytes(), err 709 } 710 711 // StdinPipe returns a pipe that will be connected to the command's 712 // standard input when the command starts. 713 // The pipe will be closed automatically after Wait sees the command exit. 714 // A caller need only call Close to force the pipe to close sooner. 715 // For example, if the command being run will not exit until standard input 716 // is closed, the caller must close the pipe. 717 func (c *Cmd) StdinPipe() (io.WriteCloser, error) { 718 if c.Stdin != nil { 719 return nil, errors.New("exec: Stdin already set") 720 } 721 if c.Process != nil { 722 return nil, errors.New("exec: StdinPipe after process started") 723 } 724 pr, pw, err := os.Pipe() 725 if err != nil { 726 return nil, err 727 } 728 c.Stdin = pr 729 c.closeAfterStart = append(c.closeAfterStart, pr) 730 wc := &closeOnce{File: pw} 731 c.closeAfterWait = append(c.closeAfterWait, wc) 732 return wc, nil 733 } 734 735 type closeOnce struct { 736 *os.File 737 738 once sync.Once 739 err error 740 } 741 742 func (c *closeOnce) Close() error { 743 c.once.Do(c.close) 744 return c.err 745 } 746 747 func (c *closeOnce) close() { 748 c.err = c.File.Close() 749 } 750 751 // StdoutPipe returns a pipe that will be connected to the command's 752 // standard output when the command starts. 753 // 754 // Wait will close the pipe after seeing the command exit, so most callers 755 // need not close the pipe themselves. It is thus incorrect to call Wait 756 // before all reads from the pipe have completed. 757 // For the same reason, it is incorrect to call Run when using StdoutPipe. 758 // See the example for idiomatic usage. 759 func (c *Cmd) StdoutPipe() (io.ReadCloser, error) { 760 if c.Stdout != nil { 761 return nil, errors.New("exec: Stdout already set") 762 } 763 if c.Process != nil { 764 return nil, errors.New("exec: StdoutPipe after process started") 765 } 766 pr, pw, err := os.Pipe() 767 if err != nil { 768 return nil, err 769 } 770 c.Stdout = pw 771 c.closeAfterStart = append(c.closeAfterStart, pw) 772 c.closeAfterWait = append(c.closeAfterWait, pr) 773 return pr, nil 774 } 775 776 // StderrPipe returns a pipe that will be connected to the command's 777 // standard error when the command starts. 778 // 779 // Wait will close the pipe after seeing the command exit, so most callers 780 // need not close the pipe themselves. It is thus incorrect to call Wait 781 // before all reads from the pipe have completed. 782 // For the same reason, it is incorrect to use Run when using StderrPipe. 783 // See the StdoutPipe example for idiomatic usage. 784 func (c *Cmd) StderrPipe() (io.ReadCloser, error) { 785 if c.Stderr != nil { 786 return nil, errors.New("exec: Stderr already set") 787 } 788 if c.Process != nil { 789 return nil, errors.New("exec: StderrPipe after process started") 790 } 791 pr, pw, err := os.Pipe() 792 if err != nil { 793 return nil, err 794 } 795 c.Stderr = pw 796 c.closeAfterStart = append(c.closeAfterStart, pw) 797 c.closeAfterWait = append(c.closeAfterWait, pr) 798 return pr, nil 799 } 800 801 // prefixSuffixSaver is an io.Writer which retains the first N bytes 802 // and the last N bytes written to it. The Bytes() methods reconstructs 803 // it with a pretty error message. 804 type prefixSuffixSaver struct { 805 N int // max size of prefix or suffix 806 prefix []byte 807 suffix []byte // ring buffer once len(suffix) == N 808 suffixOff int // offset to write into suffix 809 skipped int64 810 811 // TODO(bradfitz): we could keep one large []byte and use part of it for 812 // the prefix, reserve space for the '... Omitting N bytes ...' message, 813 // then the ring buffer suffix, and just rearrange the ring buffer 814 // suffix when Bytes() is called, but it doesn't seem worth it for 815 // now just for error messages. It's only ~64KB anyway. 816 } 817 818 func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) { 819 lenp := len(p) 820 p = w.fill(&w.prefix, p) 821 822 // Only keep the last w.N bytes of suffix data. 823 if overage := len(p) - w.N; overage > 0 { 824 p = p[overage:] 825 w.skipped += int64(overage) 826 } 827 p = w.fill(&w.suffix, p) 828 829 // w.suffix is full now if p is non-empty. Overwrite it in a circle. 830 for len(p) > 0 { // 0, 1, or 2 iterations. 831 n := copy(w.suffix[w.suffixOff:], p) 832 p = p[n:] 833 w.skipped += int64(n) 834 w.suffixOff += n 835 if w.suffixOff == w.N { 836 w.suffixOff = 0 837 } 838 } 839 return lenp, nil 840 } 841 842 // fill appends up to len(p) bytes of p to *dst, such that *dst does not 843 // grow larger than w.N. It returns the un-appended suffix of p. 844 func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) { 845 if remain := w.N - len(*dst); remain > 0 { 846 add := minInt(len(p), remain) 847 *dst = append(*dst, p[:add]...) 848 p = p[add:] 849 } 850 return p 851 } 852 853 func (w *prefixSuffixSaver) Bytes() []byte { 854 if w.suffix == nil { 855 return w.prefix 856 } 857 if w.skipped == 0 { 858 return append(w.prefix, w.suffix...) 859 } 860 var buf bytes.Buffer 861 buf.Grow(len(w.prefix) + len(w.suffix) + 50) 862 buf.Write(w.prefix) 863 buf.WriteString("\n... omitting ") 864 buf.WriteString(strconv.FormatInt(w.skipped, 10)) 865 buf.WriteString(" bytes ...\n") 866 buf.Write(w.suffix[w.suffixOff:]) 867 buf.Write(w.suffix[:w.suffixOff]) 868 return buf.Bytes() 869 } 870 871 func minInt(a, b int) int { 872 if a < b { 873 return a 874 } 875 return b 876 } 877 878 // environ returns a best-effort copy of the environment in which the command 879 // would be run as it is currently configured. If an error occurs in computing 880 // the environment, it is returned alongside the best-effort copy. 881 func (c *Cmd) environ() ([]string, error) { 882 var err error 883 884 env := c.Env 885 if env == nil { 886 env, err = execenv.Default(c.SysProcAttr) 887 if err != nil { 888 env = os.Environ() 889 // Note that the non-nil err is preserved despite env being overridden. 890 } 891 892 if c.Dir != "" { 893 switch runtime.GOOS { 894 case "windows", "plan9": 895 // Windows and Plan 9 do not use the PWD variable, so we don't need to 896 // keep it accurate. 897 default: 898 // On POSIX platforms, PWD represents βan absolute pathname of the 899 // current working directory.β Since we are changing the working 900 // directory for the command, we should also update PWD to reflect that. 901 // 902 // Unfortunately, we didn't always do that, so (as proposed in 903 // https://go.dev/issue/50599) to avoid unintended collateral damage we 904 // only implicitly update PWD when Env is nil. That way, we're much 905 // less likely to override an intentional change to the variable. 906 if pwd, absErr := filepath.Abs(c.Dir); absErr == nil { 907 env = append(env, "PWD="+pwd) 908 } else if err == nil { 909 err = absErr 910 } 911 } 912 } 913 } 914 915 env, dedupErr := dedupEnv(env) 916 if err == nil { 917 err = dedupErr 918 } 919 return addCriticalEnv(env), err 920 } 921 922 // Environ returns a copy of the environment in which the command would be run 923 // as it is currently configured. 924 func (c *Cmd) Environ() []string { 925 // Intentionally ignore errors: environ returns a best-effort environment no matter what. 926 env, _ := c.environ() 927 return env 928 } 929 930 // dedupEnv returns a copy of env with any duplicates removed, in favor of 931 // later values. 932 // Items not of the normal environment "key=value" form are preserved unchanged. 933 // Except on Plan 9, items containing NUL characters are removed, and 934 // an error is returned along with the remaining values. 935 func dedupEnv(env []string) ([]string, error) { 936 return dedupEnvCase(runtime.GOOS == "windows", runtime.GOOS == "plan9", env) 937 } 938 939 // dedupEnvCase is dedupEnv with a case option for testing. 940 // If caseInsensitive is true, the case of keys is ignored. 941 // If nulOK is false, items containing NUL characters are allowed. 942 func dedupEnvCase(caseInsensitive, nulOK bool, env []string) ([]string, error) { 943 // Construct the output in reverse order, to preserve the 944 // last occurrence of each key. 945 var err error 946 out := make([]string, 0, len(env)) 947 saw := make(map[string]bool, len(env)) 948 for n := len(env); n > 0; n-- { 949 kv := env[n-1] 950 951 // Reject NUL in environment variables to prevent security issues (#56284); 952 // except on Plan 9, which uses NUL as os.PathListSeparator (#56544). 953 if !nulOK && strings.IndexByte(kv, 0) != -1 { 954 err = errors.New("exec: environment variable contains NUL") 955 continue 956 } 957 958 i := strings.Index(kv, "=") 959 if i == 0 { 960 // We observe in practice keys with a single leading "=" on Windows. 961 // TODO(#49886): Should we consume only the first leading "=" as part 962 // of the key, or parse through arbitrarily many of them until a non-"="? 963 i = strings.Index(kv[1:], "=") + 1 964 } 965 if i < 0 { 966 if kv != "" { 967 // The entry is not of the form "key=value" (as it is required to be). 968 // Leave it as-is for now. 969 // TODO(#52436): should we strip or reject these bogus entries? 970 out = append(out, kv) 971 } 972 continue 973 } 974 k := kv[:i] 975 if caseInsensitive { 976 k = strings.ToLower(k) 977 } 978 if saw[k] { 979 continue 980 } 981 982 saw[k] = true 983 out = append(out, kv) 984 } 985 986 // Now reverse the slice to restore the original order. 987 for i := 0; i < len(out)/2; i++ { 988 j := len(out) - i - 1 989 out[i], out[j] = out[j], out[i] 990 } 991 992 return out, err 993 } 994 995 // addCriticalEnv adds any critical environment variables that are required 996 // (or at least almost always required) on the operating system. 997 // Currently this is only used for Windows. 998 func addCriticalEnv(env []string) []string { 999 if runtime.GOOS != "windows" { 1000 return env 1001 } 1002 for _, kv := range env { 1003 k, _, ok := strings.Cut(kv, "=") 1004 if !ok { 1005 continue 1006 } 1007 if strings.EqualFold(k, "SYSTEMROOT") { 1008 // We already have it. 1009 return env 1010 } 1011 } 1012 return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT")) 1013 } 1014 1015 // ErrDot indicates that a path lookup resolved to an executable 1016 // in the current directory due to β.β being in the path, either 1017 // implicitly or explicitly. See the package documentation for details. 1018 // 1019 // Note that functions in this package do not return ErrDot directly. 1020 // Code should use errors.Is(err, ErrDot), not err == ErrDot, 1021 // to test whether a returned error err is due to this condition. 1022 var ErrDot = errors.New("cannot run executable found relative to current directory") 1023