github.com/iDigitalFlame/xmt@v0.5.4/device/xy_nix_no_crypt.go (about)

     1  //go:build !windows && !js && !crypt
     2  // +build !windows,!js,!crypt
     3  
     4  // Copyright (C) 2020 - 2023 iDigitalFlame
     5  //
     6  // This program is free software: you can redistribute it and/or modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // any later version.
    10  //
    11  // This program is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    18  //
    19  
    20  package device
    21  
    22  import (
    23  	"io"
    24  	"os"
    25  	"runtime"
    26  	"strings"
    27  
    28  	"github.com/iDigitalFlame/xmt/cmd/filter"
    29  	"github.com/iDigitalFlame/xmt/data"
    30  	"github.com/iDigitalFlame/xmt/util"
    31  	"github.com/iDigitalFlame/xmt/util/xerr"
    32  )
    33  
    34  const (
    35  	// Shell is the default machine specific command shell.
    36  	Shell = "/bin/sh"
    37  	// ShellArgs is the default machine specific command shell arguments to run
    38  	// commands.
    39  	ShellArgs = "-c"
    40  	// PowerShell is the path to the PowerShell binary, which is based on the
    41  	// underlying OS type.
    42  	PowerShell = "pwsh"
    43  )
    44  
    45  // IsDebugged returns true if the current process is attached by a debugger.
    46  func IsDebugged() bool {
    47  	for _, e := range data.ReadSplit("/proc/self/status", "\n") {
    48  		if len(e) <= 9 {
    49  			continue
    50  		}
    51  		if e[9] == ':' && e[8] == 'd' && e[0] == 'T' && e[1] == 'r' && e[5] == 'r' {
    52  			return e[len(e)-1] != '0' && e[len(e)-2] != ' ' && e[len(e)-2] != 9 && e[len(e)-2] != '\t'
    53  		}
    54  	}
    55  	return false
    56  }
    57  
    58  // UserHomeDir returns the current user's home directory.
    59  //
    60  // On Unix, including macOS, it returns the $HOME environment variable.
    61  // On Windows, it returns %USERPROFILE%.
    62  // On Plan 9, it returns the $home environment variable.
    63  // On JS/WASM it returns and empty string.
    64  //
    65  // Golang compatibility helper function.
    66  func UserHomeDir() string {
    67  	if OS == Plan9 {
    68  		return os.Getenv("home")
    69  	}
    70  	if v := os.Getenv("HOME"); len(v) > 0 {
    71  		return v
    72  	}
    73  	switch OS {
    74  	case IOS:
    75  		return "/"
    76  	case Android:
    77  		return os.Getenv("/sdcard")
    78  	}
    79  	return ""
    80  }
    81  
    82  // Logins returns an array that contains information about current logged
    83  // in users.
    84  //
    85  // This call is OS-independent but many contain invalid session types.
    86  //
    87  // Always returns an EINVAL on WSAM/JS.
    88  func Logins() ([]Login, error) {
    89  	b, err := data.ReadFile("/var/run/utmp")
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	return readWhoEntries(b), nil
    94  }
    95  
    96  // Mounts attempts to get the mount points on the local device.
    97  //
    98  // On Windows devices, this is the drive letters available, otherwise on nix*
    99  // systems, this will be the mount points on the system.
   100  //
   101  // The return result (if no errors occurred) will be a string list of all the
   102  // mount points (or Windows drive letters).
   103  func Mounts() ([]string, error) {
   104  	// 0 - READONLY
   105  	f, err := os.OpenFile("/proc/self/mounts", 0, 0)
   106  	if err != nil {
   107  		// 0 - READONLY
   108  		if f, err = os.OpenFile("/etc/mtab", 0, 0); err != nil {
   109  			return nil, xerr.Wrap("cannot find mounts", err)
   110  		}
   111  	}
   112  	b, err := data.ReadAll(f)
   113  	if f.Close(); err != nil {
   114  		return nil, err
   115  	}
   116  	var (
   117  		e = strings.Split(string(b), "\n")
   118  		m = make([]string, 0, len(e))
   119  	)
   120  	for _, v := range e {
   121  		x, l := 0, 0
   122  		for s := 0; s < 2; s++ {
   123  			for l = x; x < len(v)-1 && v[x] != ' ' && v[x] != 9; x++ {
   124  			}
   125  			if x < len(v)-1 && s == 0 {
   126  				x++
   127  			}
   128  		}
   129  		if l == x {
   130  			continue
   131  		}
   132  		m = append(m, v[l:x])
   133  	}
   134  	return m, nil
   135  }
   136  
   137  // DumpProcess will attempt to copy the memory of the targeted Filter to the
   138  // supplied Writer. This fill select the first process that matches the Filter.
   139  //
   140  // If the Filter is nil or empty or if an error occurs during reading/writing
   141  // an error will be returned.
   142  //
   143  // This function may fail if attempting to dump a process that is a different CPU
   144  // architecture that the host process.
   145  func DumpProcess(f *filter.Filter, w io.Writer) error {
   146  	if f.Empty() {
   147  		return filter.ErrNoProcessFound
   148  	}
   149  	p, err := f.SelectFunc(nil)
   150  	if err != nil {
   151  		return err
   152  	}
   153  	v := "/proc/" + util.Uitoa(uint64(p))
   154  	b, err := data.ReadFile(v + "/maps")
   155  	if err != nil {
   156  		return err
   157  	}
   158  	// 0 - READONLY
   159  	d, err := os.OpenFile(v+"/mem", 0, 0)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	for _, e := range strings.Split(string(b), "\n") {
   164  		if err = parseLine(e, d, w); err != nil {
   165  			break
   166  		}
   167  	}
   168  	d.Close()
   169  	runtime.GC()
   170  	FreeOSMemory()
   171  	return err
   172  }