diff --git a/internal/applets/applet.go b/internal/applets/applet.go index 2aadd27..324c807 100644 --- a/internal/applets/applet.go +++ b/internal/applets/applet.go @@ -68,6 +68,7 @@ import ( "github.com/nao1215/mimixbox/internal/applets/shellutils/serial" "github.com/nao1215/mimixbox/internal/applets/shellutils/sleep" "github.com/nao1215/mimixbox/internal/applets/shellutils/sync" + "github.com/nao1215/mimixbox/internal/applets/shellutils/tee" "github.com/nao1215/mimixbox/internal/applets/shellutils/true" "github.com/nao1215/mimixbox/internal/applets/shellutils/uuidgen" "github.com/nao1215/mimixbox/internal/applets/shellutils/wget" @@ -155,6 +156,7 @@ func init() { "sync": {sync.Run, "Synchronize cached writes to persistent storage"}, "tac": {tac.Run, "Print the file contents from the end to the beginning"}, "tail": {tail.Run, "Print the last NUMBER(default=10) lines"}, + "tee": {tee.Run, "Read from standard input and write to standard output and files"}, "touch": {touch.Run, "Update the access and modification times of each FILE to the current time"}, "tr": {tr.Run, "Translate or delete characters"}, "true": {true.Run, "Do nothing. Return success(0)"}, diff --git a/internal/applets/shellutils/tee/tee.go b/internal/applets/shellutils/tee/tee.go new file mode 100644 index 0000000..8f7f5ac --- /dev/null +++ b/internal/applets/shellutils/tee/tee.go @@ -0,0 +1,75 @@ +package tee + +import ( + "io" + "os" + "os/signal" + "syscall" + + "github.com/jessevdk/go-flags" + mb "github.com/nao1215/mimixbox/internal/lib" +) + +type options struct { + Version bool `short:"v" long:"version" description:"print version and exit"` + Append bool `short:"a" long:"append" description:"append to files, do not overwrite"` + IgnoreSIGINT bool `short:"i" long:"ignore-interrupts" description:"ignore SIGINT"` +} + +const cmdName string = "tee" +const version = "1.0.1" + +func initParser(opts *options) *flags.Parser { + parser := flags.NewParser(opts, flags.Default) + parser.Name = cmdName + parser.Usage = "[OPTIONS]" + + return parser +} + +func Run() (int, error) { + var opts options + args, err := initParser(&opts).Parse() + if err != nil { + return mb.ExitFailure, err + } + + if opts.Version { + mb.ShowVersion(cmdName, version) + os.Exit(mb.ExitSuccess) + } + + openFlags := os.O_WRONLY | os.O_CREATE + if opts.Append { + openFlags |= os.O_APPEND + } + + if opts.IgnoreSIGINT { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT) + go func() { + for range sigs { + } + }() + + } + + files := make([]io.Writer, 0, 1+len(args)) + files = append(files, os.Stdout) + for _, filename := range args { + f, err := os.OpenFile(filename, openFlags, 0644) + if err != nil { + return mb.ExitFailure, err + } + files = append(files, f) + defer f.Close() + } + + multiwriter := io.MultiWriter(files...) + _, err = io.Copy(multiwriter, os.Stdin) + if err != nil { + return mb.ExitFailure, err + } + + return mb.ExitSuccess, nil +}