
* command/terminal: allow restart to change process args Add -args flag to "restart" command. For example, "restart -args a b c" will pass args a b c to the new process. Add "-c" flag to pass the checkpoint name. This is needed to disambiguate the checkpoint name and arglist. Reverted unnecessary changes. * Applied reviewer comments. Vendored argv. Change the syntax of restart. When the target is is in recording mode, it always interprets the args as a checkpoint. Otherwise, it interprets the args as commandline args. The flag "-args" is still there, to handle the case in which the user wants to pass an empty args on restart. * Add restartargs.go. Change "restart -args" to "restart -noargs" to clarify that this flag is used to start a process with an empty arg.
80 lines
1.4 KiB
Go
80 lines
1.4 KiB
Go
package argv
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// Run execute cmdline string and return the output
|
|
func Run(cmdline []rune, env map[string]string) ([]rune, error) {
|
|
args, err := Argv(cmdline, env, Run)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cmds, err := Cmds(args)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
output := bytes.NewBuffer(make([]byte, 0, 1024))
|
|
err = Pipe(nil, output, cmds...)
|
|
str := output.String()
|
|
str = strings.TrimSpace(str)
|
|
return []rune(str), err
|
|
}
|
|
|
|
// Cmds generate exec.Cmd for each command.
|
|
func Cmds(args [][]string) ([]*exec.Cmd, error) {
|
|
var cmds []*exec.Cmd
|
|
for _, argv := range args {
|
|
if len(argv) == 0 {
|
|
return nil, errors.New("invalid cmd")
|
|
}
|
|
|
|
cmds = append(cmds, exec.Command(argv[0], argv[1:]...))
|
|
}
|
|
return cmds, nil
|
|
}
|
|
|
|
// Pipe pipe previous command's stdout to next command's stdin, if in or
|
|
// out is nil, it will be ignored.
|
|
func Pipe(in io.Reader, out io.Writer, cmds ...*exec.Cmd) error {
|
|
l := len(cmds)
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
|
|
var err error
|
|
for i := 1; i < l; i++ {
|
|
cmds[i].Stdin, err = cmds[i-1].StdoutPipe()
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if in != nil {
|
|
cmds[0].Stdin = in
|
|
}
|
|
if out != nil {
|
|
cmds[l-1].Stdout = out
|
|
}
|
|
for i := range cmds {
|
|
err = cmds[i].Start()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for i := range cmds {
|
|
err = cmds[i].Wait()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|