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 }