//go:build linux

package process

import (
	
	
	
	
	
	
	
	
	
	

	

	
	
	
)

var PageSize = uint64(os.Getpagesize())

const (
	PrioProcess = 0   // linux/resource.h
	ClockTicks  = 100 // C.sysconf(C._SC_CLK_TCK)
)

// MemoryInfoExStat is different between OSes
type MemoryInfoExStat struct {
	RSS    uint64 `json:"rss"`    // bytes
	VMS    uint64 `json:"vms"`    // bytes
	Shared uint64 `json:"shared"` // bytes
	Text   uint64 `json:"text"`   // bytes
	Lib    uint64 `json:"lib"`    // bytes
	Data   uint64 `json:"data"`   // bytes
	Dirty  uint64 `json:"dirty"`  // bytes
}

func ( MemoryInfoExStat) () string {
	,  := json.Marshal()
	return string()
}

type MemoryMapsStat struct {
	Path         string `json:"path"`
	Rss          uint64 `json:"rss"`
	Size         uint64 `json:"size"`
	Pss          uint64 `json:"pss"`
	SharedClean  uint64 `json:"sharedClean"`
	SharedDirty  uint64 `json:"sharedDirty"`
	PrivateClean uint64 `json:"privateClean"`
	PrivateDirty uint64 `json:"privateDirty"`
	Referenced   uint64 `json:"referenced"`
	Anonymous    uint64 `json:"anonymous"`
	Swap         uint64 `json:"swap"`
}

// String returns JSON value of the process.
func ( MemoryMapsStat) () string {
	,  := json.Marshal()
	return string()
}

// Ppid returns Parent Process ID of the process.
func ( *Process) () (int32, error) {
	return .PpidWithContext(context.Background())
}

func ( *Process) ( context.Context) (int32, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return -1, 
	}
	return , nil
}

// Name returns name of the process.
func ( *Process) () (string, error) {
	return .NameWithContext(context.Background())
}

func ( *Process) ( context.Context) (string, error) {
	if .name == "" {
		if  := .fillFromStatusWithContext();  != nil {
			return "", 
		}
	}
	return .name, nil
}

// Tgid returns tgid, a Linux-synonym for user-space Pid
func ( *Process) () (int32, error) {
	if .tgid == 0 {
		if  := .fillFromStatusWithContext(context.Background());  != nil {
			return 0, 
		}
	}
	return .tgid, nil
}

// Exe returns executable path of the process.
func ( *Process) () (string, error) {
	return .ExeWithContext(context.Background())
}

func ( *Process) ( context.Context) (string, error) {
	return .fillFromExeWithContext()
}

// Cmdline returns the command line arguments of the process as a string with
// each argument separated by 0x20 ascii character.
func ( *Process) () (string, error) {
	return .CmdlineWithContext(context.Background())
}

func ( *Process) ( context.Context) (string, error) {
	return .fillFromCmdlineWithContext()
}

// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument.
func ( *Process) () ([]string, error) {
	return .CmdlineSliceWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]string, error) {
	return .fillSliceFromCmdlineWithContext()
}

func ( *Process) ( context.Context) (int64, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return 0, 
	}
	return , nil
}

// Cwd returns current working directory of the process.
func ( *Process) () (string, error) {
	return .CwdWithContext(context.Background())
}

func ( *Process) ( context.Context) (string, error) {
	return .fillFromCwdWithContext()
}

// Parent returns parent Process of the process.
func ( *Process) () (*Process, error) {
	return .ParentWithContext(context.Background())
}

func ( *Process) ( context.Context) (*Process, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return nil, 
	}
	if .parent == 0 {
		return nil, fmt.Errorf("wrong number of parents")
	}
	return NewProcess(.parent)
}

// Status returns the process status.
// Return value could be one of these.
// R: Running S: Sleep T: Stop I: Idle
// Z: Zombie W: Wait L: Lock
// The character is same within all supported platforms.
func ( *Process) () (string, error) {
	return .StatusWithContext(context.Background())
}

func ( *Process) ( context.Context) (string, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return "", 
	}
	return .status, nil
}

// Foreground returns true if the process is in foreground, false otherwise.
func ( *Process) () (bool, error) {
	return .ForegroundWithContext(context.Background())
}

func ( *Process) ( context.Context) (bool, error) {
	// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "stat")
	,  := os.ReadFile()
	if  != nil {
		return false, 
	}
	 := strings.Fields(string())
	if len() < 8 {
		return false, fmt.Errorf("insufficient data in %s", )
	}
	 := [4]
	 := [7]
	return  == , nil
}

// Uids returns user ids of the process as a slice of the int
func ( *Process) () ([]int32, error) {
	return .UidsWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []int32{}, 
	}
	return .uids, nil
}

// Gids returns group ids of the process as a slice of the int
func ( *Process) () ([]int32, error) {
	return .GidsWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []int32{}, 
	}
	return .gids, nil
}

func ( *Process) ( context.Context) ([]int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []int32{}, 
	}
	return .groups, nil
}

// Terminal returns a terminal which is associated with the process.
func ( *Process) () (string, error) {
	return .TerminalWithContext(context.Background())
}

func ( *Process) ( context.Context) (string, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return "", 
	}
	,  := getTerminalMap()
	if  != nil {
		return "", 
	}
	 := []
	return , nil
}

// Nice returns a nice value (priority).
// Notice: gopsutil can not set nice value.
func ( *Process) () (int32, error) {
	return .NiceWithContext(context.Background())
}

func ( *Process) ( context.Context) (int32, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return 0, 
	}
	return , nil
}

// IOnice returns process I/O nice value (priority).
func ( *Process) () (int32, error) {
	return .IOniceWithContext(context.Background())
}

func ( *Process) ( context.Context) (int32, error) {
	return 0, common.ErrNotImplementedError
}

// Rlimit returns Resource Limits.
func ( *Process) () ([]RlimitStat, error) {
	return .RlimitWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]RlimitStat, error) {
	return .RlimitUsage(false)
}

// RlimitUsage returns Resource Limits.
// If gatherUsed is true, the currently used value will be gathered and added
// to the resulting RlimitStat.
func ( *Process) ( bool) ([]RlimitStat, error) {
	return .RlimitUsageWithContext(context.Background(), )
}

func ( *Process) ( context.Context,  bool) ([]RlimitStat, error) {
	,  := .fillFromLimitsWithContext()
	if ! ||  != nil {
		return , 
	}

	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return nil, 
	}
	if  := .fillFromStatusWithContext();  != nil {
		return nil, 
	}

	for  := range  {
		 := &[]
		switch .Resource {
		case RLIMIT_CPU:
			,  := .Times()
			if  != nil {
				return nil, 
			}
			.Used = uint64(.User + .System)
		case RLIMIT_DATA:
			.Used = uint64(.memInfo.Data)
		case RLIMIT_STACK:
			.Used = uint64(.memInfo.Stack)
		case RLIMIT_RSS:
			.Used = uint64(.memInfo.RSS)
		case RLIMIT_NOFILE:
			,  := .NumFDs()
			if  != nil {
				return nil, 
			}
			.Used = uint64()
		case RLIMIT_MEMLOCK:
			.Used = uint64(.memInfo.Locked)
		case RLIMIT_AS:
			.Used = uint64(.memInfo.VMS)
		case RLIMIT_LOCKS:
			// TODO we can get the used value from /proc/$pid/locks. But linux doesn't enforce it, so not a high priority.
		case RLIMIT_SIGPENDING:
			.Used = .sigInfo.PendingProcess
		case RLIMIT_NICE:
			// The rlimit for nice is a little unusual, in that 0 means the niceness cannot be decreased beyond the current value, but it can be increased.
			// So effectively: if rs.Soft == 0 { rs.Soft = rs.Used }
			.Used = uint64()
		case RLIMIT_RTPRIO:
			.Used = uint64()
		}
	}

	return , 
}

// IOCounters returns IO Counters.
func ( *Process) () (*IOCountersStat, error) {
	return .IOCountersWithContext(context.Background())
}

func ( *Process) ( context.Context) (*IOCountersStat, error) {
	return .fillFromIOWithContext()
}

// NumCtxSwitches returns the number of the context switches of the process.
func ( *Process) () (*NumCtxSwitchesStat, error) {
	return .NumCtxSwitchesWithContext(context.Background())
}

func ( *Process) ( context.Context) (*NumCtxSwitchesStat, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return nil, 
	}
	return .numCtxSwitches, nil
}

// NumFDs returns the number of File Descriptors used by the process.
func ( *Process) () (int32, error) {
	return .NumFDsWithContext(context.Background())
}

func ( *Process) ( context.Context) (int32, error) {
	, ,  := .fillFromfdListWithContext()
	return int32(len()), 
}

// NumThreads returns the number of threads used by the process.
func ( *Process) () (int32, error) {
	return .NumThreadsWithContext(context.Background())
}

func ( *Process) ( context.Context) (int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return 0, 
	}
	return .numThreads, nil
}

func ( *Process) () (map[int32]*cpu.TimesStat, error) {
	return .ThreadsWithContext(context.Background())
}

func ( *Process) ( context.Context) (map[int32]*cpu.TimesStat, error) {
	 := make(map[int32]*cpu.TimesStat)
	 := common.HostProc(strconv.Itoa(int(.Pid)), "task")

	,  := readPidsFromDir()
	if  != nil {
		return nil, 
	}

	for ,  := range  {
		, , , , , , ,  := .fillFromTIDStatWithContext(, )
		if  != nil {
			return nil, 
		}
		[] = 
	}

	return , nil
}

// Times returns CPU times of the process.
func ( *Process) () (*cpu.TimesStat, error) {
	return .TimesWithContext(context.Background())
}

func ( *Process) ( context.Context) (*cpu.TimesStat, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

// CPUAffinity returns CPU affinity of the process.
//
// Notice: Not implemented yet.
func ( *Process) () ([]int32, error) {
	return .CPUAffinityWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]int32, error) {
	return nil, common.ErrNotImplementedError
}

// MemoryInfo returns platform in-dependend memory information, such as RSS, VMS and Swap
func ( *Process) () (*MemoryInfoStat, error) {
	return .MemoryInfoWithContext(context.Background())
}

func ( *Process) ( context.Context) (*MemoryInfoStat, error) {
	, ,  := .fillFromStatmWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

// MemoryInfoEx returns platform dependend memory information.
func ( *Process) () (*MemoryInfoExStat, error) {
	return .MemoryInfoExWithContext(context.Background())
}

func ( *Process) ( context.Context) (*MemoryInfoExStat, error) {
	, ,  := .fillFromStatmWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

// PageFaultsInfo returns the process's page fault counters
func ( *Process) () (*PageFaultsStat, error) {
	return .PageFaultsWithContext(context.Background())
}

func ( *Process) ( context.Context) (*PageFaultsStat, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

// Children returns a slice of Process of the process.
func ( *Process) () ([]*Process, error) {
	return .ChildrenWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]*Process, error) {
	,  := common.CallPgrepWithContext(, invoke, .Pid)
	if  != nil {
		if  == nil || len() == 0 {
			return nil, ErrorNoChildren
		}
		return nil, 
	}
	 := make([]*Process, 0, len())
	for ,  := range  {
		,  := NewProcess()
		if  != nil {
			return nil, 
		}
		 = append(, )
	}
	return , nil
}

// OpenFiles returns a slice of OpenFilesStat opend by the process.
// OpenFilesStat includes a file path and file descriptor.
func ( *Process) () ([]OpenFilesStat, error) {
	return .OpenFilesWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]OpenFilesStat, error) {
	, ,  := .fillFromfdWithContext()
	if  != nil {
		return nil, 
	}
	 := make([]OpenFilesStat, len())
	for ,  := range  {
		[] = *
	}

	return , nil
}

// Connections returns a slice of net.ConnectionStat used by the process.
// This returns all kind of the connection. This measn TCP, UDP or UNIX.
func ( *Process) () ([]net.ConnectionStat, error) {
	return .ConnectionsWithContext(context.Background())
}

func ( *Process) ( context.Context) ([]net.ConnectionStat, error) {
	return net.ConnectionsPid("all", .Pid)
}

// Connections returns a slice of net.ConnectionStat used by the process at most `max`
func ( *Process) ( int) ([]net.ConnectionStat, error) {
	return .ConnectionsMaxWithContext(context.Background(), )
}

func ( *Process) ( context.Context,  int) ([]net.ConnectionStat, error) {
	return net.ConnectionsPidMax("all", .Pid, )
}

// NetIOCounters returns NetIOCounters of the process.
func ( *Process) ( bool) ([]net.IOCountersStat, error) {
	return .NetIOCountersWithContext(context.Background(), )
}

func ( *Process) ( context.Context,  bool) ([]net.IOCountersStat, error) {
	 := common.HostProc(strconv.Itoa(int(.Pid)), "net/dev")
	return net.IOCountersByFile(, )
}

// MemoryMaps get memory maps from /proc/(pid)/smaps
func ( *Process) ( bool) (*[]MemoryMapsStat, error) {
	return .MemoryMapsWithContext(context.Background(), )
}

func ( *Process) ( context.Context,  bool) (*[]MemoryMapsStat, error) {
	 := .Pid
	var  []MemoryMapsStat
	if  {
		 = make([]MemoryMapsStat, 1)
	}
	 := common.HostProc(strconv.Itoa(int()), "smaps")
	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}
	 := strings.Split(string(), "\n")

	// function of parsing a block
	 := func(,  []string) (MemoryMapsStat, error) {
		 := MemoryMapsStat{}
		.Path = [len()-1]

		for ,  := range  {
			if strings.Contains(, "VmFlags") {
				continue
			}
			 := strings.Split(, ":")
			if len() < 2 {
				continue
			}
			 := strings.Trim([1], "kB") // remove last "kB"
			 = strings.TrimSpace()
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return , 
			}

			switch [0] {
			case "Size":
				.Size = 
			case "Rss":
				.Rss = 
			case "Pss":
				.Pss = 
			case "Shared_Clean":
				.SharedClean = 
			case "Shared_Dirty":
				.SharedDirty = 
			case "Private_Clean":
				.PrivateClean = 
			case "Private_Dirty":
				.PrivateDirty = 
			case "Referenced":
				.Referenced = 
			case "Anonymous":
				.Anonymous = 
			case "Swap":
				.Swap = 
			}
		}
		return , nil
	}

	 := make([]string, 16)
	for ,  := range  {
		 := strings.Fields()
		if len() > 0 && !strings.HasSuffix([0], ":") {
			// new block section
			if len() > 0 {
				,  := (, )
				if  != nil {
					return &, 
				}
				if  {
					[0].Size += .Size
					[0].Rss += .Rss
					[0].Pss += .Pss
					[0].SharedClean += .SharedClean
					[0].SharedDirty += .SharedDirty
					[0].PrivateClean += .PrivateClean
					[0].PrivateDirty += .PrivateDirty
					[0].Referenced += .Referenced
					[0].Anonymous += .Anonymous
					[0].Swap += .Swap
				} else {
					 = append(, )
				}
			}
			// starts new block
			 = make([]string, 16)
		} else {
			 = append(, )
		}
	}

	return &, nil
}

/**
** Internal functions
**/

func limitToInt( string) (int32, error) {
	if  == "unlimited" {
		return math.MaxInt32, nil
	} else {
		,  := strconv.ParseInt(, 10, 32)
		if  != nil {
			return 0, 
		}
		return int32(), nil
	}
}

// Get num_fds from /proc/(pid)/limits
func ( *Process) ( context.Context) ([]RlimitStat, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "limits")
	,  := os.Open()
	if  != nil {
		return nil, 
	}
	defer .Close()

	var  []RlimitStat

	 := bufio.NewScanner()
	for .Scan() {
		var  RlimitStat

		 := strings.Fields(.Text())

		// Remove the header line
		if strings.Contains([len()-1], "Units") {
			continue
		}

		// Assert that last item is a Hard limit
		.Hard,  = limitToInt([len()-1])
		if  != nil {
			// On error remove last item an try once again since it can be unit or header line
			 = [:len()-1]
			.Hard,  = limitToInt([len()-1])
			if  != nil {
				return nil, 
			}
		}
		// Remove last item from string
		 = [:len()-1]

		// Now last item is a Soft limit
		.Soft,  = limitToInt([len()-1])
		if  != nil {
			return nil, 
		}
		// Remove last item from string
		 = [:len()-1]

		// The rest is a stats name
		 := strings.Join(, " ")
		switch  {
		case "Max cpu time":
			.Resource = RLIMIT_CPU
		case "Max file size":
			.Resource = RLIMIT_FSIZE
		case "Max data size":
			.Resource = RLIMIT_DATA
		case "Max stack size":
			.Resource = RLIMIT_STACK
		case "Max core file size":
			.Resource = RLIMIT_CORE
		case "Max resident set":
			.Resource = RLIMIT_RSS
		case "Max processes":
			.Resource = RLIMIT_NPROC
		case "Max open files":
			.Resource = RLIMIT_NOFILE
		case "Max locked memory":
			.Resource = RLIMIT_MEMLOCK
		case "Max address space":
			.Resource = RLIMIT_AS
		case "Max file locks":
			.Resource = RLIMIT_LOCKS
		case "Max pending signals":
			.Resource = RLIMIT_SIGPENDING
		case "Max msgqueue size":
			.Resource = RLIMIT_MSGQUEUE
		case "Max nice priority":
			.Resource = RLIMIT_NICE
		case "Max realtime priority":
			.Resource = RLIMIT_RTPRIO
		case "Max realtime timeout":
			.Resource = RLIMIT_RTTIME
		default:
			continue
		}

		 = append(, )
	}

	if  := .Err();  != nil {
		return nil, 
	}

	return , nil
}

// Get list of /proc/(pid)/fd files
func ( *Process) ( context.Context) (string, []string, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "fd")
	,  := os.Open()
	if  != nil {
		return , []string{}, 
	}
	defer .Close()
	,  := .Readdirnames(-1)
	return , , 
}

// Get num_fds from /proc/(pid)/fd
func ( *Process) ( context.Context) (int32, []*OpenFilesStat, error) {
	, ,  := .fillFromfdListWithContext()
	if  != nil {
		return 0, nil, 
	}
	 := int32(len())

	var  []*OpenFilesStat
	for ,  := range  {
		 := filepath.Join(, )
		,  := os.Readlink()
		if  != nil {
			continue
		}
		,  := strconv.ParseUint(, 10, 64)
		if  != nil {
			return , , 
		}
		 := &OpenFilesStat{
			Path: ,
			Fd:   ,
		}
		 = append(, )
	}

	return , , nil
}

// Get cwd from /proc/(pid)/cwd
func ( *Process) ( context.Context) (string, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "cwd")
	,  := os.Readlink()
	if  != nil {
		return "", 
	}
	return string(), nil
}

// Get exe from /proc/(pid)/exe
func ( *Process) ( context.Context) (string, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "exe")
	,  := os.Readlink()
	if  != nil {
		return "", 
	}
	return string(), nil
}

// Get cmdline from /proc/(pid)/cmdline
func ( *Process) ( context.Context) (string, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "cmdline")
	,  := os.ReadFile()
	if  != nil {
		return "", 
	}
	 := strings.FieldsFunc(string(), func( rune) bool {
		if  == '\u0000' {
			return true
		}
		return false
	})

	return strings.Join(, " "), nil
}

func ( *Process) ( context.Context) ([]string, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "cmdline")
	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}
	if len() == 0 {
		return nil, nil
	}
	if [len()-1] == 0 {
		 = [:len()-1]
	}
	 := bytes.Split(, []byte{0})
	var  []string
	for ,  := range  {
		 = append(, string())
	}

	return , nil
}

// Get IO status from /proc/(pid)/io
func ( *Process) ( context.Context) (*IOCountersStat, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "io")
	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}
	 := strings.Split(string(), "\n")
	 := &IOCountersStat{}

	for ,  := range  {
		 := strings.Fields()
		if len() < 2 {
			continue
		}
		,  := strconv.ParseUint([1], 10, 64)
		if  != nil {
			return nil, 
		}
		 := [0]
		if strings.HasSuffix(, ":") {
			 = [:len()-1]
		}
		switch  {
		case "syscr":
			.ReadCount = 
		case "syscw":
			.WriteCount = 
		case "read_bytes":
			.ReadBytes = 
		case "write_bytes":
			.WriteBytes = 
		}
	}

	return , nil
}

// Get memory info from /proc/(pid)/statm
func ( *Process) ( context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "statm")
	,  := os.ReadFile()
	if  != nil {
		return nil, nil, 
	}
	 := strings.Split(string(), " ")

	,  := strconv.ParseUint([0], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([1], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	 := &MemoryInfoStat{
		RSS:  * PageSize,
		VMS:  * PageSize,
	}

	,  := strconv.ParseUint([2], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([3], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([4], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([5], 10, 64)
	if  != nil {
		return nil, nil, 
	}

	 := &MemoryInfoExStat{
		RSS:     * PageSize,
		VMS:     * PageSize,
		Shared:  * PageSize,
		Text:    * PageSize,
		Lib:     * PageSize,
		Dirty:   * PageSize,
	}

	return , , nil
}

// Get various status from /proc/(pid)/status
func ( *Process) ( context.Context) error {
	 := .Pid
	 := common.HostProc(strconv.Itoa(int()), "status")
	,  := os.ReadFile()
	if  != nil {
		return 
	}
	 := strings.Split(string(), "\n")
	.numCtxSwitches = &NumCtxSwitchesStat{}
	.memInfo = &MemoryInfoStat{}
	.sigInfo = &SignalInfoStat{}
	for ,  := range  {
		 := strings.SplitN(, "\t", 2)
		if len() < 2 {
			continue
		}
		 := [1]
		switch strings.TrimRight([0], ":") {
		case "Name":
			.name = strings.Trim(, " \t")
			if len(.name) >= 15 {
				,  := .CmdlineSlice()
				if  != nil {
					return 
				}
				if len() > 0 {
					 := filepath.Base([0])
					if strings.HasPrefix(, .name) {
						.name = 
					} else {
						.name = [0]
					}
				}
			}
		case "State":
			.status = [0:1]
		case "PPid", "Ppid":
			,  := strconv.ParseInt(, 10, 32)
			if  != nil {
				return 
			}
			.parent = int32()
		case "Tgid":
			,  := strconv.ParseInt(, 10, 32)
			if  != nil {
				return 
			}
			.tgid = int32()
		case "Uid":
			.uids = make([]int32, 0, 4)
			for ,  := range strings.Split(, "\t") {
				,  := strconv.ParseInt(, 10, 32)
				if  != nil {
					return 
				}
				.uids = append(.uids, int32())
			}
		case "Gid":
			.gids = make([]int32, 0, 4)
			for ,  := range strings.Split(, "\t") {
				,  := strconv.ParseInt(, 10, 32)
				if  != nil {
					return 
				}
				.gids = append(.gids, int32())
			}
		case "Groups":
			 := strings.Fields()
			.groups = make([]int32, 0, len())
			for ,  := range  {
				,  := strconv.ParseInt(, 10, 32)
				if  != nil {
					return 
				}
				.groups = append(.groups, int32())
			}
		case "Threads":
			,  := strconv.ParseInt(, 10, 32)
			if  != nil {
				return 
			}
			.numThreads = int32()
		case "voluntary_ctxt_switches":
			,  := strconv.ParseInt(, 10, 64)
			if  != nil {
				return 
			}
			.numCtxSwitches.Voluntary = 
		case "nonvoluntary_ctxt_switches":
			,  := strconv.ParseInt(, 10, 64)
			if  != nil {
				return 
			}
			.numCtxSwitches.Involuntary = 
		case "VmRSS":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.RSS =  * 1024
		case "VmSize":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.VMS =  * 1024
		case "VmSwap":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Swap =  * 1024
		case "VmHWM":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.HWM =  * 1024
		case "VmData":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Data =  * 1024
		case "VmStk":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Stack =  * 1024
		case "VmLck":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Locked =  * 1024
		case "SigPnd":
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.PendingThread = 
		case "ShdPnd":
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.PendingProcess = 
		case "SigBlk":
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.Blocked = 
		case "SigIgn":
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.Ignored = 
		case "SigCgt":
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.Caught = 
		}

	}
	return nil
}

func ( *Process) ( context.Context,  int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
	 := .Pid
	var  string

	if  == -1 {
		 = common.HostProc(strconv.Itoa(int()), "stat")
	} else {
		 = common.HostProc(strconv.Itoa(int()), "task", strconv.Itoa(int()), "stat")
	}

	,  := os.ReadFile()
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	 := strings.Fields(string())

	 := 1
	for !strings.HasSuffix([], ")") {
		++
	}

	,  := strconv.ParseUint([+5], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	,  := strconv.ParseInt([+2], 10, 32)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseFloat([+12], 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	,  := strconv.ParseFloat([+13], 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	// There is no such thing as iotime in stat file.  As an approximation, we
	// will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux
	// docs).  Note: I am assuming at least Linux 2.6.18
	,  := strconv.ParseFloat([+40], 64)
	if  != nil {
		 = 0 // Ancient linux version, most likely
	}

	 := &cpu.TimesStat{
		CPU:    "cpu",
		User:   float64( / ClockTicks),
		System: float64( / ClockTicks),
		Iowait: float64( / ClockTicks),
	}

	,  := common.BootTimeWithContext()
	,  := strconv.ParseUint([+20], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	 := ( / uint64(ClockTicks)) + uint64()
	 := int64( * 1000)

	,  := strconv.ParseInt([+16], 10, 32)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	if  < 0 {
		 = *-1 - 1
	} else {
		 = 0
	}

	//	p.Nice = mustParseInt32(fields[18])
	// use syscall instead of parse Stat file
	,  := unix.Getpriority(PrioProcess, int())
	 := int32() // FIXME: is this true?

	,  := strconv.ParseUint([+8], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseUint([+9], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseUint([+10], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseUint([+11], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	 := &PageFaultsStat{
		MinorFaults:      ,
		MajorFaults:      ,
		ChildMinorFaults: ,
		ChildMajorFaults: ,
	}

	return , int32(), , , uint32(), , , nil
}

func ( *Process) ( context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
	return .fillFromTIDStatWithContext(, -1)
}

func pidsWithContext( context.Context) ([]int32, error) {
	return readPidsFromDir(common.HostProc())
}

// Process returns a slice of pointers to Process structs for all
// currently running processes.
func () ([]*Process, error) {
	return ProcessesWithContext(context.Background())
}

func ( context.Context) ([]*Process, error) {
	 := []*Process{}

	,  := PidsWithContext()
	if  != nil {
		return , 
	}

	for ,  := range  {
		,  := NewProcess()
		if  != nil {
			continue
		}
		 = append(, )
	}

	return , nil
}

func readPidsFromDir( string) ([]int32, error) {
	var  []int32

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

	,  := .Readdirnames(-1)
	if  != nil {
		return nil, 
	}
	for ,  := range  {
		,  := strconv.ParseInt(, 10, 32)
		if  != nil {
			// if not numeric name, just skip
			continue
		}
		 = append(, int32())
	}

	return , nil
}