github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/core/tee/tee.go (about) 1 // Copyright 2013-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Tee transcribes the standard input to the standard output and makes copies 6 // in the files. 7 // 8 // Synopsis: 9 // 10 // tee [-ai] FILES... 11 // 12 // Options: 13 // 14 // -a, --append: append the output to the files rather than rewriting them 15 // -i, --ignore-interrupts: ignore the SIGINT signal 16 package main 17 18 import ( 19 "fmt" 20 "io" 21 "log" 22 "os" 23 "os/signal" 24 25 flag "github.com/spf13/pflag" 26 ) 27 28 var ( 29 cat = flag.BoolP("append", "a", false, "append the output to the files rather than rewriting them") 30 ignore = flag.BoolP("ignore-interrupts", "i", false, "ignore the SIGINT signal") 31 ) 32 33 type command struct { 34 stdin io.Reader 35 stdout io.Writer 36 stderr io.Writer 37 args []string 38 cat bool 39 ignore bool 40 } 41 42 func newCommand(cat, ignore bool, args []string) *command { 43 return &command{ 44 stdin: os.Stdin, 45 stdout: os.Stdout, 46 stderr: os.Stderr, 47 cat: cat, 48 ignore: ignore, 49 args: args, 50 } 51 } 52 53 func (c *command) run() error { 54 oflags := os.O_WRONLY | os.O_CREATE 55 if c.cat { 56 oflags |= os.O_APPEND 57 } 58 59 if c.ignore { 60 signal.Ignore(os.Interrupt) 61 } 62 63 files := make([]*os.File, 0, len(c.args)) 64 writers := make([]io.Writer, 0, len(c.args)+1) 65 for _, fname := range c.args { 66 f, err := os.OpenFile(fname, oflags, 0o666) 67 if err != nil { 68 return fmt.Errorf("error opening %s: %v", fname, err) 69 } 70 files = append(files, f) 71 writers = append(writers, f) 72 } 73 writers = append(writers, c.stdout) 74 75 mw := io.MultiWriter(writers...) 76 if _, err := io.Copy(mw, c.stdin); err != nil { 77 return fmt.Errorf("error: %v", err) 78 } 79 80 for _, f := range files { 81 if err := f.Close(); err != nil { 82 fmt.Fprintf(c.stderr, "tee: error closing file %q: %v\n", f.Name(), err) 83 } 84 } 85 86 return nil 87 } 88 89 func main() { 90 flag.Parse() 91 if err := newCommand(*cat, *ignore, flag.Args()).run(); err != nil { 92 log.Fatalf("tee: %v", err) 93 } 94 }