github.com/iDigitalFlame/xmt@v0.5.4/cmd/util.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package cmd 18 19 import ( 20 "github.com/iDigitalFlame/xmt/cmd/filter" 21 "github.com/iDigitalFlame/xmt/util" 22 "github.com/iDigitalFlame/xmt/util/xerr" 23 ) 24 25 var ( 26 // ErrNotStarted is an error returned by multiple functions when attempting 27 // to access a Runnable function that requires the Runnable to be started first. 28 ErrNotStarted = xerr.Sub("process has not started", 0x3A) 29 // ErrEmptyCommand is an error returned when attempting to start a Runnable 30 // that has empty arguments. 31 ErrEmptyCommand = xerr.Sub("process arguments are empty", 0x3B) 32 // ErrStillRunning is returned when attempting to access the exit code on a 33 // Runnable. 34 ErrStillRunning = xerr.Sub("process still running", 0x3C) 35 // ErrAlreadyStarted is an error returned by the 'Start' or 'Run' functions 36 // when attempting to start a Runnable that has already been started via a 37 // 'Start' or 'Run' function call. 38 ErrAlreadyStarted = xerr.Sub("process already started", 0x3D) 39 ) 40 41 // ExitError is a type of error that is returned by the Wait and Run functions 42 // when a function returns an error code other than zero. 43 type ExitError struct { 44 Exit uint32 45 } 46 47 // Runnable is an interface that helps support the type of structs that can be 48 // used for execution, such as Assembly, DLL and Process, which share the same 49 // methods as this interface. 50 type Runnable interface { 51 Run() error 52 Pid() uint32 53 Wait() error 54 Stop() error 55 Start() error 56 Running() bool 57 Release() error 58 Handle() (uintptr, error) 59 ExitCode() (int32, error) 60 SetParent(*filter.Filter) 61 } 62 63 // Split will attempt to split the specified string based on the escape characters 64 // and spaces while attempting to preserve anything that is not a splitting space. 65 // 66 // This will automatically detect quotes and backslashes. The return result is a 67 // string array that can be used as args. 68 func Split(v string) []string { 69 var ( 70 r []string 71 s int 72 ) 73 for i, m := 0, byte(0); i < len(v); i++ { 74 switch { 75 case v[i] == '\\' && i+1 < len(v) && (v[i+1] == '"' || v[i+1] == '\''): 76 i++ 77 case v[i] == ' ' && m == 0 && s == i: 78 case v[i] == ' ' && m == 0: 79 r, s = append(r, v[s:i]), i+1 80 case (v[i] == '"' || v[i] == '\'') && m == 0: 81 s, m = i+1, v[i] 82 case (v[i] == '"' || v[i] == '\'') && m == v[i]: 83 r, m, s = append(r, v[s:i]), 0, i+1 84 } 85 } 86 if s < len(v) { 87 r = append(r, v[s:]) 88 } 89 return r 90 } 91 92 // Error fulfills the error interface and returns a formatted string that 93 // specifies the Process Exit Code. 94 func (e ExitError) Error() string { 95 return "exit " + util.Itoa(int64(e.Exit)) 96 }