package daemon

import (
	
	
	
	

	
)

// SpawnConfig keeps configurations for spawning the daemon.
type SpawnConfig struct {
	// BinPath is the path to the Elvish binary itself, used when forking. This
	// field is used only when spawning the daemon. If empty, it is
	// automatically determined with os.Executable.
	BinPath string
	// DbPath is the path to the database.
	DbPath string
	// SockPath is the path to the socket on which the daemon will serve
	// requests.
	SockPath string
	// RunDir is the directory in which to place the daemon log file.
	RunDir string
}

// Spawn spawns a daemon process in the background by invoking BinPath, passing
// BinPath, DbPath and SockPath as command-line arguments after resolving them
// to absolute paths. The daemon log file is created in RunDir, and the stdout
// and stderr of the daemon is redirected to the log file.
//
// A suitable ProcAttr is chosen depending on the OS and makes sure that the
// daemon is detached from the current terminal, so that it is not affected by
// I/O or signals in the current terminal and keeps running after the current
// process quits.
func ( *SpawnConfig) error {
	 := .BinPath
	// Determine binPath.
	if  == "" {
		,  := os.Executable()
		if  != nil {
			return errors.New("cannot find elvish: " + .Error())
		}
		 = 
	}

	var  error
	 := func( string,  string) string {
		if  != nil {
			return ""
		}
		if  == "" {
			 = fmt.Errorf("%s is required for spawning daemon", )
			return ""
		}
		,  := filepath.Abs()
		if  != nil {
			 = fmt.Errorf("cannot resolve %s to absolute path: %s", , )
		}
		return 
	}
	 = ("BinPath", )
	 := ("DbPath", .DbPath)
	 := ("SockPath", .SockPath)
	 := ("RunDir", .RunDir)
	if  != nil {
		return 
	}

	 := []string{
		,
		"-daemon",
		"-bin", ,
		"-db", ,
		"-sock", ,
	}

	,  := fsutil.ClaimFile(, "daemon-*.log")
	if  != nil {
		return 
	}
	defer .Close()

	// The daemon does not read any input; open DevNull and use it for stdin. We
	// could also just close the stdin, but on Unix that would make the first
	// file opened by the daemon take FD 0.
	,  := os.OpenFile(os.DevNull, os.O_RDONLY, 0)
	if  != nil {
		 = os.Stdin
	} else {
		defer .Close()
	}

	 := procAttrForSpawn([]*os.File{, , })
	_,  = os.StartProcess(, , )

	return 
}