From 8ef26fd9749e29e721b0f5655f71579334ee458d Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Thu, 27 Apr 2023 15:17:24 +0200 Subject: [PATCH] feat: add CLI to use it every day --- cmd/pwgen/main.go | 68 +++++++++++++++++++++++++++++++++++++++++++ cmd/pwgen/terminal.go | 26 +++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 cmd/pwgen/main.go create mode 100644 cmd/pwgen/terminal.go diff --git a/cmd/pwgen/main.go b/cmd/pwgen/main.go new file mode 100644 index 0000000..1f7284d --- /dev/null +++ b/cmd/pwgen/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "code.icb4dc0.de/prskr/go-pwgen" + "flag" + "fmt" + "log" + "os" + "strings" +) + +// although there might be terminals where it's less, let's be pessimistic +const tabWidth = 8 + +var ( + length uint + count int + letters uint + lowercase uint + uppercase uint + digits uint + specials uint + specialsAlphabet string +) + +func main() { + flags := flag.NewFlagSet("pwgen", flag.ExitOnError) + flags.IntVar(&count, "count", 20, "Number of passwords to generate") + flags.UintVar(&length, "length", 20, "Length of each password to generate") + flags.UintVar(&letters, "letters", 0, "Number of letters to include at least") + flags.UintVar(&lowercase, "lowercase", 3, "Number of lowercase characters to include at least") + flags.UintVar(&uppercase, "uppercase", 3, "Number of uppercase characters to include at least") + flags.UintVar(&digits, "digits", 3, "Number of digits to include at least") + flags.UintVar(&specials, "specials", 0, "Number of special characters to include at least") + flags.StringVar(&specialsAlphabet, "specials-alphabet", pwgen.DefaultSpecialsAlphabet, "Special characters to include as special characters") + + if err := flags.Parse(os.Args[1:]); err != nil { + log.Fatalf("Failed to parse arguments: %v", err) + } + + terminalWidth := getWidth() + + passwordsPerRow := int(terminalWidth / (length + tabWidth)) + + builder := strings.Builder{} + for i := 0; i < count; i += passwordsPerRow { + for j := 0; j < passwordsPerRow && i+j < count; j++ { + pw, err := pwgen.Generate( + pwgen.WithLength(length), + pwgen.WithLetters(letters), + pwgen.WithLowercase(lowercase), + pwgen.WithUppercase(uppercase), + pwgen.WithDigits(digits), + pwgen.WithSpecials(specials), + pwgen.WithSpecialsAlphabet(specialsAlphabet), + ) + if err != nil { + log.Fatalf("Error occurred generating password: %v", err) + } + + builder.WriteString(pw) + builder.WriteRune('\t') + } + + fmt.Println(strings.TrimSuffix(builder.String(), "\t")) + builder.Reset() + } +} diff --git a/cmd/pwgen/terminal.go b/cmd/pwgen/terminal.go new file mode 100644 index 0000000..66d9efa --- /dev/null +++ b/cmd/pwgen/terminal.go @@ -0,0 +1,26 @@ +package main + +import ( + "syscall" + "unsafe" +) + +type winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +func getWidth() uint { + ws := &winsize{} + retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL, + uintptr(syscall.Stdin), + uintptr(syscall.TIOCGWINSZ), + uintptr(unsafe.Pointer(ws))) + + if int(retCode) == -1 { + panic(errno) + } + return uint(ws.Col) +}