github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/libinit/proc_plan9.go (about)

     1  // Copyright 2014-2019 the u-root 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 libinit
     6  
     7  import (
     8  	"log"
     9  	"os"
    10  	"os/exec"
    11  	"syscall"
    12  )
    13  
    14  // WaitOrphans waits for all remaining processes on the system to exit.
    15  func WaitOrphans() uint {
    16  	var numReaped uint
    17  	for {
    18  		var (
    19  			w syscall.Waitmsg
    20  		)
    21  		err := syscall.Await(&w)
    22  		if err != nil {
    23  			break
    24  		}
    25  		log.Printf("Exited with %v", w)
    26  		numReaped++
    27  	}
    28  	return numReaped
    29  }
    30  
    31  // WithRforkFlags adds rfork flags to the *exec.Cmd.
    32  func WithRforkFlags(flags uintptr) CommandModifier {
    33  	return func(c *exec.Cmd) {
    34  		if c.SysProcAttr == nil {
    35  			c.SysProcAttr = &syscall.SysProcAttr{}
    36  		}
    37  		c.SysProcAttr.Rfork = int(flags)
    38  	}
    39  }
    40  
    41  func init() {
    42  	osDefault = plan9Default
    43  }
    44  
    45  func plan9Default(c *exec.Cmd) {
    46  	c.SysProcAttr = &syscall.SysProcAttr{}
    47  }
    48  
    49  // FIX ME: make it not linux-specific
    50  // RunCommands runs commands in sequence.
    51  //
    52  // RunCommands returns how many commands existed and were attempted to run.
    53  //
    54  // commands must refer to absolute paths at the moment.
    55  func RunCommands(debug func(string, ...interface{}), commands ...*exec.Cmd) int {
    56  	var cmdCount int
    57  	for _, cmd := range commands {
    58  		if _, err := os.Stat(cmd.Path); os.IsNotExist(err) {
    59  			debug("%v", err)
    60  			continue
    61  		}
    62  
    63  		cmdCount++
    64  		debug("Trying to run %v", cmd)
    65  		if err := cmd.Start(); err != nil {
    66  			log.Printf("Error starting %v: %v", cmd, err)
    67  			continue
    68  		}
    69  
    70  		for {
    71  			var w syscall.Waitmsg
    72  			if err := syscall.Await(&w); err != nil {
    73  				debug("Error from Await: %v", err)
    74  				break
    75  			}
    76  			if w.Pid == cmd.Process.Pid {
    77  				debug("Shell exited, exit status %v", w)
    78  				break
    79  			}
    80  			debug("Reaped PID %d, exit status %v", w.Pid, w)
    81  		}
    82  		if err := cmd.Process.Release(); err != nil {
    83  			log.Printf("Error releasing process %v: %v", cmd, err)
    84  		}
    85  	}
    86  	return cmdCount
    87  }