github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/common/platform/ctlcmd/ctlcmd.go (about)

     1  package ctlcmd
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"os/exec"
     7  	"strings"
     8  
     9  	"github.com/xtls/xray-core/common/buf"
    10  	"github.com/xtls/xray-core/common/platform"
    11  )
    12  
    13  //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
    14  
    15  func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
    16  	xctl := platform.GetToolLocation("xctl")
    17  	if _, err := os.Stat(xctl); err != nil {
    18  		return nil, newError("xctl doesn't exist").Base(err)
    19  	}
    20  
    21  	var errBuffer buf.MultiBufferContainer
    22  	var outBuffer buf.MultiBufferContainer
    23  
    24  	cmd := exec.Command(xctl, args...)
    25  	cmd.Stderr = &errBuffer
    26  	cmd.Stdout = &outBuffer
    27  	cmd.SysProcAttr = getSysProcAttr()
    28  	if input != nil {
    29  		cmd.Stdin = input
    30  	}
    31  
    32  	if err := cmd.Start(); err != nil {
    33  		return nil, newError("failed to start xctl").Base(err)
    34  	}
    35  
    36  	if err := cmd.Wait(); err != nil {
    37  		msg := "failed to execute xctl"
    38  		if errBuffer.Len() > 0 {
    39  			msg += ": \n" + strings.TrimSpace(errBuffer.MultiBuffer.String())
    40  		}
    41  		return nil, newError(msg).Base(err)
    42  	}
    43  
    44  	// log stderr, info message
    45  	if !errBuffer.IsEmpty() {
    46  		newError("<xctl message> \n", strings.TrimSpace(errBuffer.MultiBuffer.String())).AtInfo().WriteToLog()
    47  	}
    48  
    49  	return outBuffer.MultiBuffer, nil
    50  }