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 }