github.com/jlowellwofford/u-root@v1.0.0/xcmds/ash/main.go (about) 1 // Copyright 2012-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 package main 6 7 import ( 8 "flag" 9 "io" 10 "log" 11 "os" 12 "os/exec" 13 14 "github.com/u-root/u-root/pkg/complete" 15 "github.com/u-root/u-root/pkg/termios" 16 ) 17 18 var ( 19 debug = flag.Bool("d", false, "enable debug prints") 20 v = func(string, ...interface{}) {} 21 ) 22 23 func verbose(f string, a ...interface{}) { 24 v(f+"\r\n", a...) 25 } 26 27 func output(r io.Reader, w io.Writer) { 28 for { 29 var b [1]byte 30 n, err := r.Read(b[:]) 31 if err == io.EOF { 32 return 33 } 34 if err != nil { 35 log.Printf("output: %v", err) 36 return 37 } 38 if n < len(b) { 39 continue 40 } 41 var s string 42 switch b[0] { 43 default: 44 s = string(b[:]) 45 case '\b', 127: 46 s = "\b \b" 47 case '\r', '\n': 48 s = "\r\n" 49 } 50 if _, err := w.Write([]byte(s)); err != nil { 51 log.Printf("output write: %v", err) 52 return 53 } 54 } 55 } 56 57 func main() { 58 flag.Parse() 59 if *debug { 60 v = log.Printf 61 complete.Debug = verbose 62 } 63 t, err := termios.New() 64 if err != nil { 65 log.Fatal(err) 66 } 67 r, err := t.Raw() 68 if err != nil { 69 log.Printf("non-fatal cannot get tty: %v", err) 70 } 71 defer t.Set(r) 72 cr, cw, err := os.Pipe() 73 if err != nil { 74 log.Fatal(err) 75 } 76 go output(cr, t) 77 for { 78 p, err := complete.NewPathCompleter() 79 if err != nil { 80 log.Fatal(err) 81 } 82 c := complete.NewMultiCompleter(complete.NewStringCompleter([]string{"exit"}), p) 83 l := complete.NewLineReader(c, t, cw) 84 s, err := l.ReadOne() 85 v("ash: Readone: %v, %v", s, err) 86 if err != nil && err != complete.EOL { 87 log.Print(err) 88 continue 89 } 90 if len(s) == 0 { 91 continue 92 } 93 if s[0] == "exit" { 94 break 95 } 96 // s[0] is either the match or what they typed so far. 97 cw.Write([]byte(" ")) 98 bin := s[0] 99 var args []string 100 for err == nil { 101 c := complete.NewFileCompleter("") 102 l := complete.NewLineReader(c, t, t) 103 s, err := l.ReadOne() 104 v("ash: l.ReadOne returns %v, %v", s, err) 105 args = append(args, s...) 106 v("ash: add %v", s) 107 if err != nil { 108 log.Print(err) 109 break 110 } 111 } 112 v("ash: Done reading args") 113 cmd := exec.Command(bin, args...) 114 cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, cw, cw 115 if err := cmd.Run(); err != nil { 116 log.Print(err) 117 } 118 } 119 }