github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/lastcmd.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"strings"
     9  )
    10  
    11  var lastCommandFile = filepath.Join(userCacheDir, "o", "last_command.sh")
    12  
    13  // isProllyFilename checks if the argument is likely a filename based on the presence
    14  // of an OS-specific path separator and a ".".
    15  func isProllyFilename(arg string) bool {
    16  	return strings.ContainsRune(arg, os.PathSeparator) && strings.Contains(arg, ".")
    17  }
    18  
    19  // getCommand takes an *exec.Cmd and returns the command
    20  // it represents, but with "/usr/bin/sh -c " trimmed away
    21  // and filenames quoted.
    22  func getCommand(cmd *exec.Cmd) string {
    23  	var args []string
    24  	for _, arg := range cmd.Args[1:] {
    25  		if isProllyFilename(arg) {
    26  			// Quote what appears to be a filename (has / and .)
    27  			args = append(args, fmt.Sprintf("%q", arg))
    28  		} else {
    29  			args = append(args, arg)
    30  		}
    31  	}
    32  	s := cmd.Path + " " + strings.Join(args, " ")
    33  	return strings.TrimPrefix(s, "/usr/bin/sh -c ")
    34  }
    35  
    36  // Save the command as the "last command"
    37  func saveCommand(cmd *exec.Cmd) error {
    38  	if noWriteToCache {
    39  		return nil
    40  	}
    41  
    42  	p := lastCommandFile
    43  
    44  	// First create the folder for the lock file overview, if needed
    45  	folderPath := filepath.Dir(p)
    46  	os.MkdirAll(folderPath, os.ModePerm)
    47  
    48  	// Prepare the file
    49  	f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
    50  	if err != nil {
    51  		return err
    52  	}
    53  	defer f.Close()
    54  
    55  	// Strip the leading /usr/bin/sh -c command, if present
    56  	commandString := getCommand(cmd)
    57  
    58  	// Write the contents, ignore the number of written bytes
    59  	_, err = f.WriteString(fmt.Sprintf("#!/bin/sh\n%s\n", commandString))
    60  	return err
    61  }