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  }