mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
parent
bda9ec2483
commit
f77fd16a6c
|
@ -15,6 +15,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/elves/elvish/sys"
|
||||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
|
@ -91,6 +92,8 @@ func init() {
|
|||
&BuiltinFn{"len", wrapFn(lenFn)},
|
||||
&BuiltinFn{"count", wrapFn(count)},
|
||||
|
||||
&BuiltinFn{"fg", wrapFn(fg)},
|
||||
|
||||
&BuiltinFn{"-sleep", wrapFn(_sleep)},
|
||||
&BuiltinFn{"-stack", wrapFn(_stack)},
|
||||
&BuiltinFn{"-log", wrapFn(_log)},
|
||||
|
@ -103,6 +106,7 @@ var (
|
|||
ErrInput = errors.New("input error")
|
||||
ErrStoreNotConnected = errors.New("store not connected")
|
||||
ErrNoMatchingDir = errors.New("no matching directory")
|
||||
ErrNotInSameGroup = errors.New("not in the same process group")
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -574,6 +578,49 @@ func count(ec *EvalCtx) {
|
|||
out <- String(strconv.Itoa(n))
|
||||
}
|
||||
|
||||
func fg(ec *EvalCtx, pids ...int) {
|
||||
if len(pids) == 0 {
|
||||
throw(ErrArgs)
|
||||
}
|
||||
var thepgid int
|
||||
for i, pid := range pids {
|
||||
pgid, err := syscall.Getpgid(pid)
|
||||
maybeThrow(err)
|
||||
if i == 0 {
|
||||
thepgid = pgid
|
||||
} else if pgid != thepgid {
|
||||
throw(ErrNotInSameGroup)
|
||||
}
|
||||
}
|
||||
|
||||
err := sys.Tcsetpgrp(0, thepgid)
|
||||
maybeThrow(err)
|
||||
|
||||
errors := make([]Error, len(pids))
|
||||
|
||||
for i, pid := range pids {
|
||||
err := syscall.Kill(pid, syscall.SIGCONT)
|
||||
if err != nil {
|
||||
errors[i] = Error{err}
|
||||
}
|
||||
}
|
||||
|
||||
for i, pid := range pids {
|
||||
if errors[i] != OK {
|
||||
continue
|
||||
}
|
||||
var ws syscall.WaitStatus
|
||||
_, err = syscall.Wait4(pid, &ws, syscall.WUNTRACED, nil)
|
||||
if err != nil {
|
||||
errors[i] = Error{err}
|
||||
} else {
|
||||
errors[i] = Error{NewExternalCmdExit(ws, pid)}
|
||||
}
|
||||
}
|
||||
|
||||
throwCompositeError(errors)
|
||||
}
|
||||
|
||||
func _sleep(ec *EvalCtx, t float64) {
|
||||
time.Sleep(time.Duration(t) * time.Second)
|
||||
}
|
||||
|
|
|
@ -77,12 +77,16 @@ func (cp *compiler) pipeline(n *parse.Pipeline) OpFunc {
|
|||
errors[i] = <-errorChan
|
||||
}
|
||||
|
||||
if !allok(errors) {
|
||||
if len(errors) == 1 {
|
||||
throw(errors[0].Inner)
|
||||
} else {
|
||||
throw(MultiError{errors})
|
||||
}
|
||||
throwCompositeError(errors)
|
||||
}
|
||||
}
|
||||
|
||||
func throwCompositeError(errors []Error) {
|
||||
if !allok(errors) {
|
||||
if len(errors) == 1 {
|
||||
throw(errors[0].Inner)
|
||||
} else {
|
||||
throw(MultiError{errors})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,8 +109,15 @@ func (f flow) Error() string {
|
|||
// command was stopped rather than terminated, the Pid field contains the pid
|
||||
// of the process.
|
||||
type ExternalCmdExit struct {
|
||||
WaitStatus syscall.WaitStatus
|
||||
Pid int
|
||||
syscall.WaitStatus
|
||||
Pid int
|
||||
}
|
||||
|
||||
func NewExternalCmdExit(ws syscall.WaitStatus, pid int) error {
|
||||
if ws.Exited() && ws.ExitStatus() == 0 {
|
||||
return nil
|
||||
}
|
||||
return ExternalCmdExit{ws, pid}
|
||||
}
|
||||
|
||||
func (exit ExternalCmdExit) Error() string {
|
||||
|
|
|
@ -81,10 +81,6 @@ func (e ExternalCmd) Call(ec *EvalCtx, argVals []Value) {
|
|||
if err != nil {
|
||||
throw(fmt.Errorf("wait: %s", err.Error()))
|
||||
} else {
|
||||
if ws.Exited() && ws.ExitStatus() == 0 {
|
||||
// Do nothing
|
||||
} else {
|
||||
throw(ExternalCmdExit{ws, pid})
|
||||
}
|
||||
maybeThrow(NewExternalCmdExit(ws, pid))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user