diff --git a/job.go b/job.go index a0bdcb5..d5572b8 100644 --- a/job.go +++ b/job.go @@ -111,6 +111,7 @@ func (j *job) lua() rt.Value { jobFuncs := map[string]util.LuaExport{ "stop": {j.luaStop, 0, false}, "start": {j.luaStart, 0, false}, + "foreground": {j.luaForeground, 0, false}, } luaJob := rt.NewTable() util.SetExports(l, luaJob, jobFuncs) @@ -146,9 +147,26 @@ func (j *job) luaStop(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +func (j *job) luaForeground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { + if !j.running { + return nil, errors.New("job not running") + } + + // lua code can run in other threads and goroutines, so this exists + jobs.foreground = true + err := j.foreground() + if err != nil { + return nil, err + } + jobs.foreground = false + + return c.Next(), nil +} + type jobHandler struct { jobs map[int]*job latestID int + foreground bool // if job currently in the foreground mu *sync.RWMutex } diff --git a/job_unix.go b/job_unix.go new file mode 100644 index 0000000..3eed5b8 --- /dev/null +++ b/job_unix.go @@ -0,0 +1,28 @@ +// +build darwin linux + +package main + +import ( + "errors" + "os" + "syscall" + + "golang.org/x/sys/unix" +) + +func (j *job) foreground() error { + if jobs.foreground { + return errors.New("(another) job already foregrounded") + } + + pgid, _ := syscall.Getpgid(j.pid) + // tcsetpgrp + unix.IoctlSetPointerInt(0, unix.TIOCSPGRP, pgid) + proc, _ := os.FindProcess(j.pid) + proc.Wait() + + hshPgid, _ := syscall.Getpgid(os.Getpid()) + unix.IoctlSetPointerInt(0, unix.TIOCSPGRP, hshPgid) + + return nil +} diff --git a/job_windows.go b/job_windows.go new file mode 100644 index 0000000..270e00a --- /dev/null +++ b/job_windows.go @@ -0,0 +1,11 @@ +// +build windows + +package main + +import ( + "errors" +) + +func (j *job) foreground() error { + return errors.New("not supported on windows") +}