Handle shell built-in commands
This handles built-in shell commands. this is done by using 2 arrays:
-
unhandled_shell_builtins: A string array containing the names of built-in commands that don't work through DollarSkip (cdfor example). -
handled_shell_builtins: An array forWrapper(struct wrapper) that holds commands we wrapped so they work through DollarSkip.
To show how the handled shell built-ins work I added an "easter egg" command (e_egg). I thought about doing pwd, but I don't want to rewrite the bash version.
Closes #46
Signed-off-by: Itai-Nelken [email protected]
Something I forgot to mention: this slows down dollarskip by about 0.030 seconds.
Something I forgot to mention: this slows down dollarskip by about 0.030 seconds.
Thats an extremely long time. I'm sure the average person will notice :smile:
There is no issue.
I made a version of the changes here (excluding the "wrapping" of commands) for DollarSkip-go.
the true in all entries of the map don't do anything and are there because I wanted to use a map as it makes it possible to not use loops, and so is faster.
package main
import (
"fmt" // for printing errors
"os" // for capturing argv
"os/exec" // for running the commands
"strings" // for unslicing the array
)
var unhandled_commands = map[string]bool{
"cd": true,
"alias" : true,
"unalias" : true,
"pushd" : true,
"popd" : true,
"dirs" : true,
"read" : true,
"set" : true,
"readonly" : true,
"unset" : true,
"typeset" : true,
"declare" : true,
"disown" : true,
"enable" : true,
"export" : true,
"exit" : true, // doesn't do anything when run through DollarSkip
"fc" : true,
"history" : true,
"fg" : true,
"getopts" : true,
"hash" : true, // we don't want it to report fake data for the current shell (true for the shell in which it is run)
"jobs" : true, // same reason as the one for 'hash'
"times" : true, // same as above
"local" : true,
}
func main() {
if len(os.Args) < 2 {
os.Exit(1)
}
if _, ok := unhandled_commands[os.Args[1]]; ok {
fmt.Fprintf(os.Stderr, "\x1b[31;1m[DollarSkip: error]: '\x1b[97m%s\x1b[0;1;31m': built-in shell commands aren't supported!\x1b[0m\n", os.Args[1])
os.Exit(1)
}
args := os.Args[1:] // collects given arguments and 1: removes the binary name
unsliced_string := strings.Join(args, " ") // convert to string rather than type []string from args
shell := os.Getenv("SHELL") // Using the env, save the shell
cmd := exec.Command(shell, `-c`, unsliced_string) // Define the command to be run
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
err := cmd.Run() // Run the command
if exitErr, ok := err.(*exec.ExitError); ok {
exitCode := exitErr.ExitCode()
os.Exit(exitCode)
} else if err != nil {
exitCode := 1
os.Exit(exitCode)
}
}