//go:build linux || freebsd || openbsd || darwin || solaris
// +build linux freebsd openbsd darwin solaris

package process

import (
	
	
	
	
	
	
	
	
	

	

	
)

type Signal = syscall.Signal

// POSIX
func getTerminalMap() (map[uint64]string, error) {
	 := make(map[uint64]string)
	var  []string

	,  := os.Open("/dev")
	if  != nil {
		return nil, 
	}
	defer .Close()

	,  := .Readdirnames(-1)
	if  != nil {
		return nil, 
	}
	for ,  := range  {
		if strings.HasPrefix(, "/dev/tty") {
			 = append(, "/dev/tty/"+)
		}
	}

	var  []string
	,  := os.Open("/dev/pts")
	if  != nil {
		, _ = filepath.Glob("/dev/ttyp*")
		if  == nil {
			return nil, 
		}
	}
	defer .Close()

	if  == nil {
		defer .Close()
		,  = .Readdirnames(-1)
		if  != nil {
			return nil, 
		}
		for ,  := range  {
			 = append(, "/dev/pts/"+)
		}
	} else {
		 = 
	}

	for ,  := range  {
		 := unix.Stat_t{}
		if  = unix.Stat(, &);  != nil {
			return nil, 
		}
		 := uint64(.Rdev)
		[] = strings.Replace(, "/dev", "", -1)
	}
	return , nil
}

// isMount is a port of python's os.path.ismount()
// https://github.com/python/cpython/blob/08ff4369afca84587b1c82034af4e9f64caddbf2/Lib/posixpath.py#L186-L216
// https://docs.python.org/3/library/os.path.html#os.path.ismount
func isMount( string) bool {
	// Check symlinkness with os.Lstat; unix.DT_LNK is not portable
	,  := os.Lstat()
	if  != nil {
		return false
	}
	if .Mode()&os.ModeSymlink != 0 {
		return false
	}
	var  unix.Stat_t
	if  := unix.Lstat(, &);  != nil {
		return false
	}
	 := filepath.Join(, "..")
	var  unix.Stat_t
	if  := unix.Lstat(, &);  != nil {
		return false
	}
	return .Dev != .Dev || .Ino == .Ino
}

func ( context.Context,  int32) (bool, error) {
	if  <= 0 {
		return false, fmt.Errorf("invalid pid %v", )
	}
	,  := os.FindProcess(int())
	if  != nil {
		return false, 
	}

	if isMount(common.HostProcWithContext()) { // if /<HOST_PROC>/proc exists and is mounted, check if /<HOST_PROC>/proc/<PID> folder exists
		,  := os.Stat(common.HostProcWithContext(, strconv.Itoa(int())))
		if os.IsNotExist() {
			return false, nil
		}
		return  == nil, 
	}

	// procfs does not exist or is not mounted, check PID existence by signalling the pid
	 = .Signal(syscall.Signal(0))
	if  == nil {
		return true, nil
	}
	if errors.Is(, os.ErrProcessDone) {
		return false, nil
	}
	var  syscall.Errno
	if !errors.As(, &) {
		return false, 
	}
	switch  {
	case syscall.ESRCH:
		return false, nil
	case syscall.EPERM:
		return true, nil
	}

	return false, 
}

func ( *Process) ( context.Context,  syscall.Signal) error {
	,  := os.FindProcess(int(.Pid))
	if  != nil {
		return 
	}

	 = .Signal()
	if  != nil {
		return 
	}

	return nil
}

func ( *Process) ( context.Context) error {
	return .SendSignalWithContext(, unix.SIGSTOP)
}

func ( *Process) ( context.Context) error {
	return .SendSignalWithContext(, unix.SIGCONT)
}

func ( *Process) ( context.Context) error {
	return .SendSignalWithContext(, unix.SIGTERM)
}

func ( *Process) ( context.Context) error {
	return .SendSignalWithContext(, unix.SIGKILL)
}

func ( *Process) ( context.Context) (string, error) {
	,  := .UidsWithContext()
	if  != nil {
		return "", 
	}
	if len() > 0 {
		,  := user.LookupId(strconv.Itoa(int([0])))
		if  != nil {
			return "", 
		}
		return .Username, nil
	}
	return "", nil
}