github.com/zaolin/u-root@v0.0.0-20200428085104-64aaafd46c6d/cmds/core/strings/strings.go (about)

     1  // Copyright 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  // Strings finds printable strings.
     6  //
     7  // Synopsis:
     8  //     strings OPTIONS [FILES]...
     9  //
    10  // Description:
    11  //     Prints all sequences of `n` or more printable characters terminated by a
    12  //     non-printable character (or EOF).
    13  //
    14  //     If no files are specified, read from stdin.
    15  //
    16  // Options:
    17  //     -n number: the minimum string length (default is 4)
    18  package main
    19  
    20  import (
    21  	"bufio"
    22  	"io"
    23  	"log"
    24  	"os"
    25  
    26  	flag "github.com/spf13/pflag"
    27  )
    28  
    29  var (
    30  	n = flag.Int("n", 4, "the minimum string length")
    31  )
    32  
    33  func asciiIsPrint(char byte) bool {
    34  	return char >= 32 && char <= 126
    35  }
    36  
    37  func stringsIO(r *bufio.Reader, w io.Writer) error {
    38  	var o []byte
    39  	for {
    40  		b, err := r.ReadByte()
    41  		if err == io.EOF {
    42  			if len(o) >= *n {
    43  				w.Write(o)
    44  				w.Write([]byte{'\n'})
    45  			}
    46  			return nil
    47  		}
    48  		if err != nil {
    49  			return err
    50  		}
    51  		if !asciiIsPrint(b) {
    52  			if len(o) >= *n {
    53  				w.Write(o)
    54  				w.Write([]byte{'\n'})
    55  			}
    56  			o = o[:0]
    57  			continue
    58  		}
    59  		// Prevent the buffer from growing indefinitely.
    60  		if len(o) >= *n+1024 {
    61  			w.Write(o[:1024])
    62  			o = o[1024:]
    63  		}
    64  		o = append(o, b)
    65  	}
    66  }
    67  
    68  func stringsFile(file string, w io.Writer) error {
    69  	f, err := os.Open(file)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	defer f.Close()
    74  
    75  	// Buffer reduces number of syscalls.
    76  	rb := bufio.NewReader(f)
    77  	return stringsIO(rb, w)
    78  }
    79  
    80  func strings(files []string, w io.Writer) error {
    81  	if len(files) == 0 {
    82  		rb := bufio.NewReader(os.Stdin)
    83  		if err := stringsIO(rb, w); err != nil {
    84  			return err
    85  		}
    86  	}
    87  	for _, file := range files {
    88  		if err := stringsFile(file, w); err != nil {
    89  			return err
    90  		}
    91  	}
    92  	return nil
    93  }
    94  
    95  func main() {
    96  	flag.Parse()
    97  
    98  	if *n < 1 {
    99  		log.Fatalf("strings: invalid minimum string length %v", *n)
   100  	}
   101  
   102  	// Buffer reduces number of syscalls.
   103  	wb := bufio.NewWriter(os.Stdout)
   104  	defer wb.Flush()
   105  
   106  	if err := strings(flag.Args(), wb); err != nil {
   107  		log.Fatalf("strings: %v", err)
   108  	}
   109  }