func syntaxError() {
	fmt.Fprintf(os.Stderr, `passwordcheck - check your rclone config for bad passwords - %s
In https: 
found which meant that passwords generated by "rclone config" might be
insecure.
This program checks your rclone config file for any of those
passwords.
Note that it may take some time to run. At the end it will print a
report showing any insecure passwords found.
Usage:
    passwordcheck [options] /path/to/rclone/config/file
Note that you can find your rclone config file by running "rclone
config file".
See the README.md for more info.
Options:
`, version)
	flag.PrintDefaults()
}
syntaxError prints the syntax
package main
import (
	"bufio"
	"bytes"
	"encoding/base64"
	"flag"
	"fmt"
	"io"
	"log"
	"math/rand"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"
	"github.com/rclone/rclone/fs/config/obscure"
)
const timeFormat = "2006-01-02 15:04:05"
var (
	startDate = flag.String("start-date", "2019-08-25 00:00:00", "Start date to search from")
	endDate   = flag.String("end-date", time.Now().Format(timeFormat), "End date to search to")
	minBits   = flag.Int("min-bits", 64, "Minimum number of bits to search in a password")
	verbose   = flag.Bool("verbose", false, "Set to print more things")
	version   = "development version"  
)
type passEntry struct {
	remote   string
	pw       []byte
	obscured string
}
type foundReport struct {
	mu    sync.Mutex
	found []passEntry
}
func newFoundReport() *foundReport {
	return &foundReport{}
}
func (report *foundReport) add(pw passEntry) {
	report.mu.Lock()
	defer report.mu.Unlock()
	report.found = append(report.found, pw)
}
func debugf(format string, v ...interface{}) {
	if *verbose {
		log.Printf(format, v...)
	}
}
func password(rng *rand.Rand, pw []byte) {
	n, err := rng.Read(pw)
	if err != nil {
		log.Fatalf("password read failed: %v", err)
	}
	if n != len(pw) {
		log.Fatalf("password short read: %d", n)
	}
}
func passString(pw []byte) string {
	return base64.RawURLEncoding.EncodeToString(pw)
}
func seedString(seed int64) string {
	return fmt.Sprintf("seed %d generated at %v", seed, time.Unix(seed, 0).Format(timeFormat))
}
func readConfigFile(in io.Reader) (pws map[int][]passEntry) {
	var (
		remotes               = 0
		nonGeneratedPasswords = 0
		tooShortPasswords     = 0
		generatedPasswords    = 0
	)
	pws = make(map[int][]passEntry)
	scanner := bufio.NewScanner(in)
	remote := "UNKNOWN"
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if len(line) < 4 {
			continue
		}
		if line[0] == '[' && line[len(line)-1] == ']' {
			remote = line[1 : len(line)-1]
			remotes++
			continue
		}
		if strings.Contains(line, "RCLONE_ENCRYPT") {
			log.Fatalf("Can't read encrypted config files - please decrypt first")
		}
		if !strings.HasPrefix(line, "pass") {
			continue
		}
		equal := strings.IndexRune(line, '=')
		if equal < 0 {
			continue
		}
		key, value := strings.TrimSpace(line[:equal]), strings.TrimSpace(line[equal+1:])
		if len(value) == 0 {
			continue
		}
		if key == "pass" || key == "password" || key == "password2" {
			debugf("remote = %q, key = %q, value = %q", remote, key, value)
			pwString, err := obscure.Reveal(value)
			if err != nil {
				debugf("%s: %s = %q is not an obscured password: %v", remote, key, value, err)
				nonGeneratedPasswords++
				continue
			}
			pw, err := base64.RawURLEncoding.DecodeString(pwString)
			if err != nil {
				debugf("%s: obscured password %s = %q  was not generated by rclone: %v", remote, key, value, err)
				nonGeneratedPasswords++
				continue
			}
			if len(pw) < *minBits/8 {
				debugf("%s: IGNORING obscured password %s = %q is only %d bits (set with -min-bits)", remote, key, value, len(pw)*8)
				tooShortPasswords++
				continue
			}
			generatedPasswords++
			pws[len(pw)] = append(pws[len(pw)],
				passEntry{
					remote:   remote,
					pw:       pw,
					obscured: value,
				},
			)
		}
	}
	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	log.Printf("found %d remote definitions", remotes)
	log.Printf("found %d passwords generated by rclone config which need checking", generatedPasswords)
	log.Printf("ignored %d passwords not generated by rclone config", nonGeneratedPasswords)
	log.Printf("ignored %d passwords less than %d bits", tooShortPasswords, *minBits)
	return pws
}
const increment = 1024
func testPasswords(wg *sync.WaitGroup, seeds <-chan int64, wantPws []passEntry, found *foundReport) {
	defer wg.Done()
	if len(wantPws) == 0 {
		return
	}
	lenPw := len(wantPws[0].pw)
	rng := rand.New(rand.NewSource(1))
	var pw = make([]byte, lenPw)
	for seed := range seeds {
		for i := 0; i < increment; i++ {
			rng.Seed(seed)
			password(rng, pw)
			for _, wantPw := range wantPws {
				if bytes.Equal(pw, wantPw.pw) {
					log.Printf("FOUND match for remote %s: obscured password %q at %s", wantPw.remote, wantPw.obscured, seedString(seed))
					found.add(wantPw)
				}
			}
			seed++
		}
	}
}
func findPasswords(startSeed, endSeed int64, wantPws []passEntry) []passEntry {
	found := newFoundReport()
	var wg sync.WaitGroup
	n := runtime.NumCPU()
	seeds := make(chan int64, n)
	for i := 0; i < n; i++ {
		wg.Add(1)
		go testPasswords(&wg, seeds, wantPws, found)
	}
	for seed := startSeed; seed <= endSeed; seed += increment {
		seeds <- seed
	}
	close(seeds)
	wg.Wait()
	return found.found
}
func findAllPasswords(startSeed, endSeed int64, pwsMap map[int][]passEntry) []passEntry {
	var pws []passEntry
	var lengths []int
	for length := range pwsMap {
		lengths = append(lengths, length)
	}
	sort.Ints(lengths)
	for _, length := range lengths {
		log.Printf("Looking through %d seeds from %v to %v for %d passwords of length %d bits", endSeed-startSeed, seedString(startSeed), seedString(endSeed), len(pwsMap[length]), length*8)
		start := time.Now()
		newPws := findPasswords(startSeed, endSeed, pwsMap[length])
		dt := time.Since(start)
		pws = append(pws, newPws...)
		log.Printf("That took %v for %f seeds/s", dt, float64(endSeed-startSeed)/float64(dt)*float64(time.Second))
	}
	return pws
}
func timeParse(tString string) int64 {
	t, err := time.Parse(timeFormat, tString)
	if err != nil {
		log.Fatalf("failed to parse time %q: %v", tString, err)
	}
	return t.Unix()
}