// +build !windows,!plan9

package eval

import (
	
	
	
	
	

	
	
	
)

// ErrNotInSameProcessGroup is thrown when the process IDs passed to fg are not
// in the same process group.
var ErrNotInSameProcessGroup = errors.New("not in the same process group")

//elvdoc:fn exec
//
// ```elvish
// exec $command?
// ```
//
// Replace the Elvish process with an external `$command`, defaulting to
// `elvish`. This decrements `$E:SHLVL` before starting the new process.
//
// This command always raises an exception on Windows with the message "not
// supported on Windows".

func ( *Frame,  ...interface{}) error {
	var  []string
	if len() == 0 {
		 = []string{"elvish"}
	} else {
		 = make([]string, len())
		for ,  := range  {
			[] = vals.ToString()
		}
	}

	var  error
	[0],  = exec.LookPath([0])
	if  != nil {
		return 
	}

	preExit()
	decSHLVL()

	return syscall.Exec([0], , os.Environ())
}

// Decrements $E:SHLVL. Called from execFn to ensure that $E:SHLVL remains the
// same in the new command.
func () {
	,  := strconv.Atoi(os.Getenv(env.SHLVL))
	if  != nil {
		return
	}
	os.Setenv(env.SHLVL, strconv.Itoa(-1))
}

func ( ...int) error {
	if len() == 0 {
		return ErrArgs
	}
	var  int
	for ,  := range  {
		,  := syscall.Getpgid()
		if  != nil {
			return 
		}
		if  == 0 {
			 = 
		} else if  !=  {
			return ErrNotInSameProcessGroup
		}
	}

	 := sys.Tcsetpgrp(0, )
	if  != nil {
		return 
	}

	 := make([]Exception, len())

	for ,  := range  {
		 := syscall.Kill(, syscall.SIGCONT)
		if  != nil {
			[] = &exception{, nil}
		}
	}

	for ,  := range  {
		if [] != nil {
			continue
		}
		var  syscall.WaitStatus
		_,  = syscall.Wait4(, &, syscall.WUNTRACED, nil)
		if  != nil {
			[] = &exception{, nil}
		} else {
			// TODO find command name
			[] = &exception{NewExternalCmdExit(
				"[pid "+strconv.Itoa()+"]", , ), nil}
		}
	}

	return MakePipelineError()
}