github.com/elves/Elvish@v0.12.0/eval/builtin_fn_cmd_unix.go (about)

     1  // +build !windows,!plan9
     2  
     3  package eval
     4  
     5  import (
     6  	"os"
     7  	"os/exec"
     8  	"strconv"
     9  	"syscall"
    10  
    11  	"github.com/elves/elvish/eval/vals"
    12  	"github.com/elves/elvish/sys"
    13  )
    14  
    15  func execFn(fm *Frame, args ...interface{}) error {
    16  	var argstrings []string
    17  	if len(args) == 0 {
    18  		argstrings = []string{"elvish"}
    19  	} else {
    20  		argstrings = make([]string, len(args))
    21  		for i, a := range args {
    22  			argstrings[i] = vals.ToString(a)
    23  		}
    24  	}
    25  
    26  	var err error
    27  	argstrings[0], err = exec.LookPath(argstrings[0])
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	preExit(fm)
    33  
    34  	return syscall.Exec(argstrings[0], argstrings, os.Environ())
    35  }
    36  
    37  func fg(pids ...int) error {
    38  	if len(pids) == 0 {
    39  		return ErrArgs
    40  	}
    41  	var thepgid int
    42  	for i, pid := range pids {
    43  		pgid, err := syscall.Getpgid(pid)
    44  		if err != nil {
    45  			return err
    46  		}
    47  		if i == 0 {
    48  			thepgid = pgid
    49  		} else if pgid != thepgid {
    50  			return ErrNotInSameGroup
    51  		}
    52  	}
    53  
    54  	err := sys.Tcsetpgrp(0, thepgid)
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	errors := make([]*Exception, len(pids))
    60  
    61  	for i, pid := range pids {
    62  		err := syscall.Kill(pid, syscall.SIGCONT)
    63  		if err != nil {
    64  			errors[i] = &Exception{err, nil}
    65  		}
    66  	}
    67  
    68  	for i, pid := range pids {
    69  		if errors[i] != nil {
    70  			continue
    71  		}
    72  		var ws syscall.WaitStatus
    73  		_, err = syscall.Wait4(pid, &ws, syscall.WUNTRACED, nil)
    74  		if err != nil {
    75  			errors[i] = &Exception{err, nil}
    76  		} else {
    77  			// TODO find command name
    78  			errors[i] = &Exception{NewExternalCmdExit(
    79  				"[pid "+strconv.Itoa(pid)+"]", ws, pid), nil}
    80  		}
    81  	}
    82  
    83  	return ComposeExceptionsFromPipeline(errors)
    84  }