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  }